[Spice-commits] 18 commits - Makefile.target hppa-dis.c hw/esp.c hw/etraxfs_ser.c hw/mpc8544_guts.c hw/ppc440.c hw/ppc_mac.h hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppce500_mpc8544ds.c hw/virtex_ml507.c pc-bios/README pc-bios/mpc8544ds.dtb pc-bios/mpc8544ds.dts pc-bios/openbios-ppc target-ppc/cpu.h target-ppc/helper.c target-ppc/machine.c target-ppc/op_helper.c target-ppc/translate.c target-ppc/translate_init.c target-sparc/translate.c tcg/hppa tcg/ppc tcg/ppc64

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Jul 4 08:04:43 PDT 2011


 Makefile.target             |    2 
 hppa-dis.c                  |    6 -
 hw/esp.c                    |    2 
 hw/etraxfs_ser.c            |   24 ++++-
 hw/mpc8544_guts.c           |  135 ++++++++++++++++++++++++++++++
 hw/ppc440.c                 |    5 -
 hw/ppc_mac.h                |    3 
 hw/ppc_newworld.c           |   15 ++-
 hw/ppc_oldworld.c           |   15 ++-
 hw/ppce500_mpc8544ds.c      |   46 +++++++---
 hw/virtex_ml507.c           |    4 
 pc-bios/README              |    6 -
 pc-bios/mpc8544ds.dtb       |binary
 pc-bios/mpc8544ds.dts       |    9 ++
 pc-bios/openbios-ppc        |binary
 target-ppc/cpu.h            |   47 +++++++---
 target-ppc/helper.c         |  193 +++++++++++++++++++++++++++++++++++++++-----
 target-ppc/machine.c        |   16 +--
 target-ppc/op_helper.c      |  160 ++++++++----------------------------
 target-ppc/translate.c      |   17 +--
 target-ppc/translate_init.c |   27 +++++-
 target-sparc/translate.c    |   32 +++++--
 tcg/hppa/tcg-target.c       |   63 +++++++++-----
 tcg/hppa/tcg-target.h       |    1 
 tcg/ppc/tcg-target.c        |    7 +
 tcg/ppc64/tcg-target.c      |    7 +
 26 files changed, 592 insertions(+), 250 deletions(-)

New commits:
commit 75ef849696830fc2ddeff8bb90eea5887ff50df6
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Sat Jul 2 17:23:00 2011 +0200

    esp: correctly fill bus id with requested lun
    
    This bug showed up after 1455084ea2c48abf23c4e4e15e378ee43457f381, and
    may be seen only on operating systems *not* using DMA to give commands
    to SCSI adapter.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/esp.c b/hw/esp.c
index 6d3f5d2..8e95672 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -211,7 +211,7 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf)
     } else {
         dmalen = s->ti_size;
         memcpy(buf, s->ti_buf, dmalen);
-        buf[0] = 0;
+        buf[0] = buf[2] >> 5;
     }
     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
 
commit f74b32dec96b3298d0b33a76190ad8ea2db02869
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat May 28 08:27:20 2011 +0000

    TCG/PPC: use stack for TCG temps
    
    Use stack instead of temp_buf array in CPUState for TCG temps.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 0cd8873..58c8621 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -907,9 +907,14 @@ static void tcg_target_qemu_prologue (TCGContext *s)
         + LINKAGE_AREA_SIZE
         + TCG_STATIC_CALL_ARGS_SIZE
         + ARRAY_SIZE (tcg_target_callee_save_regs) * 4
+        + CPU_TEMP_BUF_NLONGS * sizeof(long)
         ;
     frame_size = (frame_size + 15) & ~15;
 
+    tcg_set_frame(s, TCG_REG_CALL_STACK, frame_size
+                  - CPU_TEMP_BUF_NLONGS * sizeof(long),
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
+
 #ifdef _CALL_AIX
     {
         uint32_t addr;
@@ -1914,6 +1919,4 @@ static void tcg_target_init(TCGContext *s)
 #endif
 
     tcg_add_target_add_op_defs(ppc_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 065c710..02a6cb2 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -875,9 +875,14 @@ static void tcg_target_qemu_prologue (TCGContext *s)
         + 8                     /* TOC save area */
         + TCG_STATIC_CALL_ARGS_SIZE
         + ARRAY_SIZE (tcg_target_callee_save_regs) * 8
+        + CPU_TEMP_BUF_NLONGS * sizeof(long)
         ;
     frame_size = (frame_size + 15) & ~15;
 
+    tcg_set_frame(s, TCG_REG_CALL_STACK, frame_size
+                  - CPU_TEMP_BUF_NLONGS * sizeof(long),
+                  CPU_TEMP_BUF_NLONGS * sizeof(long));
+
 #ifndef __APPLE__
     /* First emit adhoc function descriptor */
     addr = (uint64_t) s->code_ptr + 24;
@@ -1691,6 +1696,4 @@ static void tcg_target_init (TCGContext *s)
     tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13);
 
     tcg_add_target_add_op_defs (ppc_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
commit 8e91ed308062e742610e4cfdfd4a09bc045ead45
Author: Artyom Tarasenko <atar4qemu at gmail.com>
Date:   Fri Jul 1 21:28:42 2011 +0200

    fix cpu_cc_src and cpu_cc_src2 corruption in udivx and sdivx
    
    udivx and sdvix don't modify condition flags, so they shall not
    overwrite cpu_cc_*
    
    Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 992cd77..f32a674 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -727,19 +727,24 @@ static inline void gen_trap_ifdivzero_tl(TCGv divisor)
 static inline void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2)
 {
     int l1, l2;
+    TCGv r_temp1, r_temp2;
 
     l1 = gen_new_label();
     l2 = gen_new_label();
-    tcg_gen_mov_tl(cpu_cc_src, src1);
-    tcg_gen_mov_tl(cpu_cc_src2, src2);
-    gen_trap_ifdivzero_tl(cpu_cc_src2);
-    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc_src, INT64_MIN, l1);
-    tcg_gen_brcondi_tl(TCG_COND_NE, cpu_cc_src2, -1, l1);
+    r_temp1 = tcg_temp_local_new();
+    r_temp2 = tcg_temp_local_new();
+    tcg_gen_mov_tl(r_temp1, src1);
+    tcg_gen_mov_tl(r_temp2, src2);
+    gen_trap_ifdivzero_tl(r_temp2);
+    tcg_gen_brcondi_tl(TCG_COND_NE, r_temp1, INT64_MIN, l1);
+    tcg_gen_brcondi_tl(TCG_COND_NE, r_temp2, -1, l1);
     tcg_gen_movi_i64(dst, INT64_MIN);
     tcg_gen_br(l2);
     gen_set_label(l1);
-    tcg_gen_div_i64(dst, cpu_cc_src, cpu_cc_src2);
+    tcg_gen_div_i64(dst, r_temp1, r_temp2);
     gen_set_label(l2);
+    tcg_temp_free(r_temp1);
+    tcg_temp_free(r_temp2);
 }
 #endif
 
@@ -3173,10 +3178,17 @@ static void disas_sparc_insn(DisasContext * dc)
                         break;
 #ifdef TARGET_SPARC64
                     case 0xd: /* V9 udivx */
-                        tcg_gen_mov_tl(cpu_cc_src, cpu_src1);
-                        tcg_gen_mov_tl(cpu_cc_src2, cpu_src2);
-                        gen_trap_ifdivzero_tl(cpu_cc_src2);
-                        tcg_gen_divu_i64(cpu_dst, cpu_cc_src, cpu_cc_src2);
+                        {
+                            TCGv r_temp1, r_temp2;
+                            r_temp1 = tcg_temp_local_new();
+                            r_temp2 = tcg_temp_local_new();
+                            tcg_gen_mov_tl(r_temp1, cpu_src1);
+                            tcg_gen_mov_tl(r_temp2, cpu_src2);
+                            gen_trap_ifdivzero_tl(r_temp2);
+                            tcg_gen_divu_i64(cpu_dst, r_temp1, r_temp2);
+                            tcg_temp_free(r_temp1);
+                            tcg_temp_free(r_temp2);
+                        }
                         break;
 #endif
                     case 0xe: /* udiv */
commit 3b88670664f7902000b83149e7fa1875ad5c6239
Merge: ec18842... 1c53acc...
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Fri Jul 1 21:12:50 2011 +0000

    Merge branch 'ppc-next' of git://repo.or.cz/qemu/agraf
    
    * 'ppc-next' of git://repo.or.cz/qemu/agraf:
      PPC: move TLBs to their own arrays
      PPC: 440: Use 440 style MMU as default, so Qemu knows the MMU type
      PPC: E500: Use MAS registers instead of internal TLB representation
      PPC: Only set lower 32bits with mtmsr
      PPC: update openbios firmware
      PPC: mpc8544ds: Add hypervisor node
      PPC: calculate kernel,initrd,cmdline locations dynamically
      target-ppc: Handle memory-forced I/O controller access
      PPC: E500: Implement reboot controller

commit ec1884298c96a8ce723880adb9e8ffe5e71fcf37
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Jun 20 15:10:49 2011 -0700

    tcg-hppa: Support deposit opcode.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index db33e79..222f33e 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -467,6 +467,14 @@ static inline void tcg_out_dep(TCGContext *s, int ret, int arg,
               | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
 }
 
+static inline void tcg_out_depi(TCGContext *s, int ret, int arg,
+                                unsigned ofs, unsigned len)
+{
+    assert(ofs < 32 && len <= 32 - ofs);
+    tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(arg)
+              | INSN_SHDEP_CP(31 - ofs) | INSN_DEP_LEN(len));
+}
+
 static inline void tcg_out_shd(TCGContext *s, int ret, int hi, int lo,
                                unsigned count)
 {
@@ -499,8 +507,7 @@ static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
     assert(bs1 == 32 || (1ul << bs1) > m);
 
     tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
-    tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
-              | INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
+    tcg_out_depi(s, ret, -1, bs0, bs1 - bs0);
 }
 
 static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
@@ -529,8 +536,7 @@ static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
         tcg_out_extr(s, ret, arg, 0, ls0, 0);
     } else {
         tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
-        tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
-                  | INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
+        tcg_out_depi(s, ret, 0, ls0, ls1 - ls0);
     }
 }
 
@@ -1459,6 +1465,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                      args[4], args[5], const_args[2], const_args[4]);
         break;
 
+    case INDEX_op_deposit_i32:
+        if (const_args[2]) {
+            tcg_out_depi(s, args[0], args[2], args[3], args[4]);
+        } else {
+            tcg_out_dep(s, args[0], args[2], args[3], args[4]);
+        }
+        break;
+
     case INDEX_op_qemu_ld8u:
         tcg_out_qemu_ld(s, args, 0);
         break;
@@ -1552,6 +1566,8 @@ static const TCGTargetOpDef hppa_op_defs[] = {
     { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rI", "rZ" } },
     { INDEX_op_sub2_i32, { "r", "r", "rI", "rZ", "rK", "rZ" } },
 
+    { INDEX_op_deposit_i32, { "r", "0", "rJ" } },
+
 #if TARGET_LONG_BITS == 32
     { INDEX_op_qemu_ld8u, { "r", "L" } },
     { INDEX_op_qemu_ld8s, { "r", "L" } },
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index a5cc440..f7919ce 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -94,6 +94,7 @@ enum {
 #define TCG_TARGET_HAS_not_i32
 #define TCG_TARGET_HAS_andc_i32
 // #define TCG_TARGET_HAS_orc_i32
+#define TCG_TARGET_HAS_deposit_i32
 
 /* optional instructions automatically implemented */
 #undef TCG_TARGET_HAS_neg_i32           /* sub rd, 0, rs */
commit 4d506cebd35be339a38df3f96e087fc761e4cdb4
Author: Richard Henderson <rth at twiddle.net>
Date:   Mon Jun 20 15:02:29 2011 -0700

    hppa: Fix printf warnings in hppa-dis.c.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hppa-dis.c b/hppa-dis.c
index a5760a9..435da73 100644
--- a/hppa-dis.c
+++ b/hppa-dis.c
@@ -1771,13 +1771,13 @@ static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
 static void
 fput_reg (unsigned reg, disassemble_info *info)
 {
-  (*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
+  (*info->fprintf_func) (info->stream, "%s", reg ? reg_names[reg] : "r0");
 }
 
 static void
 fput_fp_reg (unsigned reg, disassemble_info *info)
 {
-  (*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
+  (*info->fprintf_func) (info->stream, "%s", reg ? fp_reg_names[reg] : "fr0");
 }
 
 static void
@@ -1794,7 +1794,7 @@ fput_fp_reg_r (unsigned reg, disassemble_info *info)
 static void
 fput_creg (unsigned reg, disassemble_info *info)
 {
-  (*info->fprintf_func) (info->stream, control_reg[reg]);
+  (*info->fprintf_func) (info->stream, "%s", control_reg[reg]);
 }
 
 /* Print constants with sign.  */
commit 2a6a665f160e95b9acda89aedcf302d18872482d
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat May 28 07:55:47 2011 +0000

    TCG/HPPA: use stack for TCG temps
    
    Use stack instead of temp_buf array in CPUState for TCG temps.
    
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index bd40954..db33e79 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1612,6 +1612,9 @@ static void tcg_target_qemu_prologue(TCGContext *s)
     /* Allocate space for the saved registers.  */
     frame_size += ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
 
+    /* Allocate space for the TCG temps. */
+    frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
+
     /* Align the allocated space.  */
     frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
                   & -TCG_TARGET_STACK_ALIGN);
@@ -1629,6 +1632,10 @@ static void tcg_target_qemu_prologue(TCGContext *s)
                    TCG_REG_CALL_STACK, -frame_size + i * 4);
     }
 
+    /* Record the location of the TCG temps.  */
+    tcg_set_frame(s, TCG_REG_CALL_STACK, -frame_size + i * 4,
+                  TCG_TEMP_BUF_NLONGS * sizeof(long));
+
 #ifdef CONFIG_USE_GUEST_BASE
     if (GUEST_BASE != 0) {
         tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
@@ -1684,6 +1691,4 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
 
     tcg_add_target_add_op_defs(hppa_op_defs);
-    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
-                  CPU_TEMP_BUF_NLONGS * sizeof(long));
 }
commit a42bceec0939b2d5d0172733eb14afafe6cfabb3
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat May 28 07:49:35 2011 +0000

    TCG/HPPA: use TCG_REG_CALL_STACK instead of TCG_REG_SP
    
    Use TCG_REG_CALL_STACK instead of TCG_REG_SP for consistency.
    
    Acked-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 79bca63..bd40954 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -646,14 +646,14 @@ static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
                           int arg1, int arg2)
 {
     /* Store both words into the stack for copy to the FPU.  */
-    tcg_out_ldst(s, arg1, TCG_REG_SP, STACK_TEMP_OFS, INSN_STW);
-    tcg_out_ldst(s, arg2, TCG_REG_SP, STACK_TEMP_OFS + 4, INSN_STW);
+    tcg_out_ldst(s, arg1, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_STW);
+    tcg_out_ldst(s, arg2, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4, INSN_STW);
 
     /* Load both words into the FPU at the same time.  We get away
        with this because we can address the left and right half of the
        FPU registers individually once loaded.  */
     /* fldds stack_temp(sp),fr22 */
-    tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_SP)
+    tcg_out32(s, INSN_FLDDS | INSN_R2(TCG_REG_CALL_STACK)
               | INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
 
     /* xmpyu fr22r,fr22,fr22 */
@@ -661,15 +661,16 @@ static void tcg_out_xmpyu(TCGContext *s, int retl, int reth,
 
     /* Store the 64-bit result back into the stack.  */
     /* fstds stack_temp(sp),fr22 */
-    tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_SP)
+    tcg_out32(s, INSN_FSTDS | INSN_R2(TCG_REG_CALL_STACK)
               | INSN_IM5(STACK_TEMP_OFS) | INSN_T(22));
 
     /* Load the pieces of the result that the caller requested.  */
     if (reth) {
-        tcg_out_ldst(s, reth, TCG_REG_SP, STACK_TEMP_OFS, INSN_LDW);
+        tcg_out_ldst(s, reth, TCG_REG_CALL_STACK, STACK_TEMP_OFS, INSN_LDW);
     }
     if (retl) {
-        tcg_out_ldst(s, retl, TCG_REG_SP, STACK_TEMP_OFS + 4, INSN_LDW);
+        tcg_out_ldst(s, retl, TCG_REG_CALL_STACK, STACK_TEMP_OFS + 4,
+                     INSN_LDW);
     }
 }
 
@@ -1198,7 +1199,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
         }
         tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R23, datahi_reg);
         tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R24, datalo_reg);
-        tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_SP,
+        tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_CALL_STACK,
                    TCG_TARGET_CALL_STACK_OFFSET - 4);
         break;
     default:
@@ -1616,16 +1617,16 @@ static void tcg_target_qemu_prologue(TCGContext *s)
                   & -TCG_TARGET_STACK_ALIGN);
 
     /* The return address is stored in the caller's frame.  */
-    tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -20);
+    tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK, -20);
 
     /* Allocate stack frame, saving the first register at the same time.  */
     tcg_out_ldst(s, tcg_target_callee_save_regs[0],
-                 TCG_REG_SP, frame_size, INSN_STWM);
+                 TCG_REG_CALL_STACK, frame_size, INSN_STWM);
 
     /* Save all callee saved registers.  */
     for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
         tcg_out_st(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
-                   TCG_REG_SP, -frame_size + i * 4);
+                   TCG_REG_CALL_STACK, -frame_size + i * 4);
     }
 
 #ifdef CONFIG_USE_GUEST_BASE
@@ -1642,16 +1643,17 @@ static void tcg_target_qemu_prologue(TCGContext *s)
     tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
 
     /* Restore callee saved registers.  */
-    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -frame_size - 20);
+    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_CALL_STACK,
+               -frame_size - 20);
     for (i = 1; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
         tcg_out_ld(s, TCG_TYPE_PTR, tcg_target_callee_save_regs[i],
-                   TCG_REG_SP, -frame_size + i * 4);
+                   TCG_REG_CALL_STACK, -frame_size + i * 4);
     }
 
     /* Deallocate stack frame and return.  */
     tcg_out32(s, INSN_BV | INSN_R2(TCG_REG_RP));
     tcg_out_ldst(s, tcg_target_callee_save_regs[0],
-                 TCG_REG_SP, -frame_size, INSN_LDWM);
+                 TCG_REG_CALL_STACK, -frame_size, INSN_LDWM);
 }
 
 static void tcg_target_init(TCGContext *s)
@@ -1678,7 +1680,7 @@ static void tcg_target_init(TCGContext *s)
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R19); /* clobbered w/o pic */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R20); /* reserved */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP);  /* data pointer */
-    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);  /* stack pointer */
+    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);  /* stack pointer */
     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
 
     tcg_add_target_add_op_defs(hppa_op_defs);
commit 20be39de592d883fc8b08d73349c70eb04e92f36
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Thu Jun 30 10:52:22 2011 +0200

    etraxfs-ser: Correct default value for RW_REC_CTRL
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 2787ebd..b917d4d 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -190,15 +190,23 @@ static void serial_event(void *opaque, int event)
 
 }
 
-static int etraxfs_ser_init(SysBusDevice *dev)
+static void etraxfs_ser_reset(DeviceState *d)
 {
-    struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
-    int ser_regs;
+    struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
 
     /* transmitter begins ready and idle.  */
     s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
     s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
 
+    s->regs[RW_REC_CTRL] = 0x10000;
+
+}
+
+static int etraxfs_ser_init(SysBusDevice *dev)
+{
+    struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+    int ser_regs;
+
     sysbus_init_irq(dev, &s->irq);
     ser_regs = cpu_register_io_memory(ser_read, ser_write, s,
                                       DEVICE_NATIVE_ENDIAN);
@@ -211,10 +219,16 @@ static int etraxfs_ser_init(SysBusDevice *dev)
     return 0;
 }
 
+static SysBusDeviceInfo etraxfs_ser_info = {
+    .init = etraxfs_ser_init,
+    .qdev.name  = "etraxfs,serial",
+    .qdev.size  = sizeof(struct etrax_serial),
+    .qdev.reset = etraxfs_ser_reset,
+};
+
 static void etraxfs_serial_register(void)
 {
-    sysbus_register_dev("etraxfs,serial", sizeof (struct etrax_serial),
-                etraxfs_ser_init);
+    sysbus_register_withprop(&etraxfs_ser_info);
 }
 
 device_init(etraxfs_serial_register)
commit 1c53accceeb01246aea0ec361e1efd15cac6db0f
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Jun 17 01:00:28 2011 +0200

    PPC: move TLBs to their own arrays
    
    Until now, we've created a union over multiple different TLB types and
    allocated that union. While it's a waste of memory (and cache) to allocate
    TLB information for a TLB type with much information when you only need
    little, it also inflicts another issue.
    
    With the new KVM API, we can now share the TLB between KVM and qemu, but
    for that to work we need to have both be in the same layout. We can't just
    stretch it over to fit some internal different TLB representation.
    
    Hence this patch moves all TLB types to their own array, allowing us to only
    address and allocate exactly the boundaries required for the specific TLB
    type at hand.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/virtex_ml507.c b/hw/virtex_ml507.c
index fa60515..7bde8c7 100644
--- a/hw/virtex_ml507.c
+++ b/hw/virtex_ml507.c
@@ -60,7 +60,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
                                      target_ulong va,
                                      target_phys_addr_t pa)
 {
-    ppcemb_tlb_t *tlb = &env->tlb[0].tlbe;
+    ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
 
     tlb->attr = 0;
     tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
@@ -69,7 +69,7 @@ static void mmubooke_create_initial_mapping(CPUState *env,
     tlb->RPN = pa & TARGET_PAGE_MASK;
     tlb->PID = 0;
 
-    tlb = &env->tlb[1].tlbe;
+    tlb = &env->tlb.tlbe[1];
     tlb->attr = 0;
     tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
     tlb->size = 1 << 31; /* up to 0xffffffff  */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 758c554..46d86be 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -368,10 +368,16 @@ typedef struct ppcmas_tlb_t {
 } ppcmas_tlb_t;
 
 union ppc_tlb_t {
-    ppc6xx_tlb_t tlb6;
-    ppcemb_tlb_t tlbe;
-    ppcmas_tlb_t tlbm;
+    ppc6xx_tlb_t *tlb6;
+    ppcemb_tlb_t *tlbe;
+    ppcmas_tlb_t *tlbm;
 };
+
+/* possible TLB variants */
+#define TLB_NONE               0
+#define TLB_6XX                1
+#define TLB_EMB                2
+#define TLB_MAS                3
 #endif
 
 #define SDR_32_HTABORG         0xFFFF0000UL
@@ -911,7 +917,8 @@ struct CPUPPCState {
     int last_way;    /* Last used way used to allocate TLB in a LRU way      */
     int id_tlbs;     /* If 1, MMU has separated TLBs for instructions & data */
     int nb_pids;     /* Number of available PID registers                    */
-    ppc_tlb_t *tlb;  /* TLB is optional. Allocate them only if needed        */
+    int tlb_type;    /* Type of TLB we're dealing with                       */
+    ppc_tlb_t tlb;   /* TLB is optional. Allocate them only if needed        */
     /* 403 dedicated access protection registers */
     target_ulong pb[4];
 #endif
@@ -1942,9 +1949,9 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
 static inline int booke206_tlbm_id(CPUState *env, ppcmas_tlb_t *tlbm)
 {
     uintptr_t tlbml = (uintptr_t)tlbm;
-    uintptr_t tlbl = (uintptr_t)env->tlb;
+    uintptr_t tlbl = (uintptr_t)env->tlb.tlbm;
 
-    return (tlbml - tlbl) / sizeof(env->tlb[0]);
+    return (tlbml - tlbl) / sizeof(env->tlb.tlbm[0]);
 }
 
 static inline int booke206_tlb_size(CPUState *env, int tlbn)
@@ -2004,7 +2011,7 @@ static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
         r += booke206_tlb_size(env, i);
     }
 
-    return &env->tlb[r].tlbm;
+    return &env->tlb.tlbm[r];
 }
 
 #endif
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 8cf9ee1..3884976 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -323,7 +323,7 @@ static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
     if (env->id_tlbs == 1)
         max *= 2;
     for (nr = 0; nr < max; nr++) {
-        tlb = &env->tlb[nr].tlb6;
+        tlb = &env->tlb.tlb6[nr];
         pte_invalidate(&tlb->pte0);
     }
     tlb_flush(env, 1);
@@ -340,7 +340,7 @@ static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
     /* Invalidate ITLB + DTLB, all ways */
     for (way = 0; way < env->nb_ways; way++) {
         nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
-        tlb = &env->tlb[nr].tlb6;
+        tlb = &env->tlb.tlb6[nr];
         if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
             LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
                       env->nb_tlb, eaddr);
@@ -367,7 +367,7 @@ void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
     int nr;
 
     nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
-    tlb = &env->tlb[nr].tlb6;
+    tlb = &env->tlb.tlb6[nr];
     LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
               " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
     /* Invalidate any pending reference in Qemu for this virtual address */
@@ -391,7 +391,7 @@ static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
     for (way = 0; way < env->nb_ways; way++) {
         nr = ppc6xx_tlb_getnum(env, eaddr, way,
                                access_type == ACCESS_CODE ? 1 : 0);
-        tlb = &env->tlb[nr].tlb6;
+        tlb = &env->tlb.tlb6[nr];
         /* This test "emulates" the PTE index match for hardware TLBs */
         if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
             LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
@@ -434,7 +434,7 @@ static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
         LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
                   ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
         /* Update page flags */
-        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
+        pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
     }
 
     return ret;
@@ -1049,7 +1049,7 @@ int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
     /* Default return value is no match */
     ret = -1;
     for (i = 0; i < env->nb_tlb; i++) {
-        tlb = &env->tlb[i].tlbe;
+        tlb = &env->tlb.tlbe[i];
         if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
             ret = i;
             break;
@@ -1066,7 +1066,7 @@ static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
     int i;
 
     for (i = 0; i < env->nb_tlb; i++) {
-        tlb = &env->tlb[i].tlbe;
+        tlb = &env->tlb.tlbe[i];
         tlb->prot &= ~PAGE_VALID;
     }
     tlb_flush(env, 1);
@@ -1082,7 +1082,7 @@ static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
     int i;
 
     for (i = 0; i < env->nb_tlb; i++) {
-        tlb = &env->tlb[i].tlbe;
+        tlb = &env->tlb.tlbe[i];
         if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
             end = tlb->EPN + tlb->size;
             for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
@@ -1107,7 +1107,7 @@ static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
     raddr = (target_phys_addr_t)-1ULL;
     pr = msr_pr;
     for (i = 0; i < env->nb_tlb; i++) {
-        tlb = &env->tlb[i].tlbe;
+        tlb = &env->tlb.tlbe[i];
         if (ppcemb_tlb_check(env, tlb, &raddr, address,
                              env->spr[SPR_40x_PID], 0, i) < 0)
             continue;
@@ -1248,7 +1248,7 @@ static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
     ret = -1;
     raddr = (target_phys_addr_t)-1ULL;
     for (i = 0; i < env->nb_tlb; i++) {
-        tlb = &env->tlb[i].tlbe;
+        tlb = &env->tlb.tlbe[i];
         ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
                                  access_type, i);
         if (!ret) {
@@ -1273,14 +1273,14 @@ void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
 {
     int tlb_size;
     int i, j;
-    ppc_tlb_t *tlb = env->tlb;
+    ppcmas_tlb_t *tlb = env->tlb.tlbm;
 
     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
         if (flags & (1 << i)) {
             tlb_size = booke206_tlb_size(env, i);
             for (j = 0; j < tlb_size; j++) {
-                if (!check_iprot || !(tlb[j].tlbm.mas1 & MAS1_IPROT)) {
-                    tlb[j].tlbm.mas1 &= ~MAS1_VALID;
+                if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
+                    tlb[j].mas1 &= ~MAS1_VALID;
                 }
             }
         }
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 0c1986e..1c40d43 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -52,12 +52,12 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_sbe32s(f, &env->last_way);
     qemu_put_sbe32s(f, &env->id_tlbs);
     qemu_put_sbe32s(f, &env->nb_pids);
-    if (env->tlb) {
+    if (env->tlb.tlb6) {
         // XXX assumes 6xx
         for (i = 0; i < env->nb_tlb; i++) {
-            qemu_put_betls(f, &env->tlb[i].tlb6.pte0);
-            qemu_put_betls(f, &env->tlb[i].tlb6.pte1);
-            qemu_put_betls(f, &env->tlb[i].tlb6.EPN);
+            qemu_put_betls(f, &env->tlb.tlb6[i].pte0);
+            qemu_put_betls(f, &env->tlb.tlb6[i].pte1);
+            qemu_put_betls(f, &env->tlb.tlb6[i].EPN);
         }
     }
     for (i = 0; i < 4; i++)
@@ -140,12 +140,12 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_sbe32s(f, &env->last_way);
     qemu_get_sbe32s(f, &env->id_tlbs);
     qemu_get_sbe32s(f, &env->nb_pids);
-    if (env->tlb) {
+    if (env->tlb.tlb6) {
         // XXX assumes 6xx
         for (i = 0; i < env->nb_tlb; i++) {
-            qemu_get_betls(f, &env->tlb[i].tlb6.pte0);
-            qemu_get_betls(f, &env->tlb[i].tlb6.pte1);
-            qemu_get_betls(f, &env->tlb[i].tlb6.EPN);
+            qemu_get_betls(f, &env->tlb.tlb6[i].pte0);
+            qemu_get_betls(f, &env->tlb.tlb6[i].pte1);
+            qemu_get_betls(f, &env->tlb.tlb6[i].EPN);
         }
     }
     for (i = 0; i < 4; i++)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 135211d..82b6651 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3959,7 +3959,7 @@ target_ulong helper_4xx_tlbre_hi (target_ulong entry)
     int size;
 
     entry &= PPC4XX_TLB_ENTRY_MASK;
-    tlb = &env->tlb[entry].tlbe;
+    tlb = &env->tlb.tlbe[entry];
     ret = tlb->EPN;
     if (tlb->prot & PAGE_VALID) {
         ret |= PPC4XX_TLBHI_V;
@@ -3979,7 +3979,7 @@ target_ulong helper_4xx_tlbre_lo (target_ulong entry)
     target_ulong ret;
 
     entry &= PPC4XX_TLB_ENTRY_MASK;
-    tlb = &env->tlb[entry].tlbe;
+    tlb = &env->tlb.tlbe[entry];
     ret = tlb->RPN;
     if (tlb->prot & PAGE_EXEC) {
         ret |= PPC4XX_TLBLO_EX;
@@ -3998,7 +3998,7 @@ void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
     LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
               val);
     entry &= PPC4XX_TLB_ENTRY_MASK;
-    tlb = &env->tlb[entry].tlbe;
+    tlb = &env->tlb.tlbe[entry];
     /* Invalidate previous TLB (if it's valid) */
     if (tlb->prot & PAGE_VALID) {
         end = tlb->EPN + tlb->size;
@@ -4056,7 +4056,7 @@ void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
     LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
               val);
     entry &= PPC4XX_TLB_ENTRY_MASK;
-    tlb = &env->tlb[entry].tlbe;
+    tlb = &env->tlb.tlbe[entry];
     tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
     tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
     tlb->prot = PAGE_READ;
@@ -4091,7 +4091,7 @@ void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
               __func__, word, (int)entry, value);
     do_flush_tlbs = 0;
     entry &= 0x3F;
-    tlb = &env->tlb[entry].tlbe;
+    tlb = &env->tlb.tlbe[entry];
     switch (word) {
     default:
         /* Just here to please gcc */
@@ -4150,7 +4150,7 @@ target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
     int size;
 
     entry &= 0x3F;
-    tlb = &env->tlb[entry].tlbe;
+    tlb = &env->tlb.tlbe[entry];
     switch (word) {
     default:
         /* Just here to please gcc */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index fc50ae3..f542b8e 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -844,6 +844,7 @@ static void gen_6xx_7xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
     env->nb_tlb = nb_tlbs;
     env->nb_ways = nb_ways;
     env->id_tlbs = 1;
+    env->tlb_type = TLB_6XX;
     spr_register(env, SPR_DMISS, "DMISS",
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, SPR_NOACCESS,
@@ -1337,6 +1338,7 @@ static void gen_74xx_soft_tlb (CPUPPCState *env, int nb_tlbs, int nb_ways)
     env->nb_tlb = nb_tlbs;
     env->nb_ways = nb_ways;
     env->id_tlbs = 1;
+    env->tlb_type = TLB_6XX;
     /* XXX : not implemented */
     spr_register(env, SPR_PTEHI, "PTEHI",
                  SPR_NOACCESS, SPR_NOACCESS,
@@ -3282,6 +3284,7 @@ static void init_proc_401x2 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_4xx_softmmu(env);
     env->dcache_line_size = 32;
@@ -3352,6 +3355,7 @@ static void init_proc_IOP480 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_4xx_softmmu(env);
     env->dcache_line_size = 32;
@@ -3431,6 +3435,7 @@ static void init_proc_403GCX (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_4xx_softmmu(env);
     env->dcache_line_size = 32;
@@ -3479,6 +3484,7 @@ static void init_proc_405 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_4xx_softmmu(env);
     env->dcache_line_size = 32;
@@ -3561,6 +3567,7 @@ static void init_proc_440EP (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_BookE(env);
     env->dcache_line_size = 32;
@@ -3624,6 +3631,7 @@ static void init_proc_440GP (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_BookE(env);
     env->dcache_line_size = 32;
@@ -3687,6 +3695,7 @@ static void init_proc_440x4 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_BookE(env);
     env->dcache_line_size = 32;
@@ -3767,6 +3776,7 @@ static void init_proc_440x5 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_BookE(env);
     env->dcache_line_size = 32;
@@ -3854,6 +3864,7 @@ static void init_proc_460 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_BookE(env);
     env->dcache_line_size = 32;
@@ -3944,6 +3955,7 @@ static void init_proc_460F (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_BookE(env);
     env->dcache_line_size = 32;
@@ -4251,6 +4263,7 @@ static void init_proc_e200 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    env->tlb_type = TLB_EMB;
 #endif
     init_excp_e200(env);
     env->dcache_line_size = 32;
@@ -4464,6 +4477,7 @@ static void init_proc_e500 (CPUPPCState *env, int version)
 
 #if !defined(CONFIG_USER_ONLY)
     env->nb_tlb = 0;
+    env->tlb_type = TLB_MAS;
     for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
         env->nb_tlb += booke206_tlb_size(env, i);
     }
@@ -9186,6 +9200,7 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
     env->nb_BATs = 0;
     env->nb_tlb = 0;
     env->nb_ways = 0;
+    env->tlb_type = TLB_NONE;
 #endif
     /* Register SPR common to all PowerPC implementations */
     gen_spr_generic(env);
@@ -9310,7 +9325,17 @@ static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
         int nb_tlb = env->nb_tlb;
         if (env->id_tlbs != 0)
             nb_tlb *= 2;
-        env->tlb = qemu_mallocz(nb_tlb * sizeof(ppc_tlb_t));
+        switch (env->tlb_type) {
+        case TLB_6XX:
+            env->tlb.tlb6 = qemu_mallocz(nb_tlb * sizeof(ppc6xx_tlb_t));
+            break;
+        case TLB_EMB:
+            env->tlb.tlbe = qemu_mallocz(nb_tlb * sizeof(ppcemb_tlb_t));
+            break;
+        case TLB_MAS:
+            env->tlb.tlbm = qemu_mallocz(nb_tlb * sizeof(ppcmas_tlb_t));
+            break;
+        }
         /* Pre-compute some useful values */
         env->tlb_per_way = env->nb_tlb / env->nb_ways;
     }
commit 0dd4bc7dd45de7afa88662d24bd50a3aafdbab64
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jun 16 18:49:22 2011 +0200

    PPC: 440: Use 440 style MMU as default, so Qemu knows the MMU type
    
    We have some KVM interaction code in Qemu that tries to be clever and
    ignore some capabilities when running on BookE style MMUs. Unfortunately,
    the default CPU bamboo was defaulting to was not a BookE-style MMU,
    resulting in the check to fail.
    
    With this patch, guests can run again on 440 with -enable-kvm.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc440.c b/hw/ppc440.c
index 1ed001a..90abc91 100644
--- a/hw/ppc440.c
+++ b/hw/ppc440.c
@@ -45,8 +45,9 @@ CPUState *ppc440ep_init(ram_addr_t *ram_size, PCIBus **pcip,
     qemu_irq *irqs;
     qemu_irq *pci_irqs;
 
-    if (cpu_model == NULL)
-        cpu_model = "405"; // XXX: should be 440EP
+    if (cpu_model == NULL) {
+        cpu_model = "440-Xilinx"; // XXX: should be 440EP
+    }
     env = cpu_init(cpu_model);
     if (!env) {
         fprintf(stderr, "Unable to initialize CPU!\n");
commit d1e256fe47be3dd43f38a8ec50f860506f975baf
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jun 16 18:45:43 2011 +0200

    PPC: E500: Use MAS registers instead of internal TLB representation
    
    The natural format for e500 cores to do TLB manipulation with are the MAS
    registers. Instead of converting them into some internal representation
    and back again when the guest reads them, we can just keep the data
    identical to the way the guest passed it to us.
    
    The main advantage of this approach is that we're getting closer to being
    able to share MMU data with KVM using shared memory, so that we don't need
    to copy lots of MMU data back and forth all the time. For this to work
    however, another patch is required that gets rid of the TLB union, as that
    destroys our memory layout that needs to be identical with the kernel one.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 073de3c..b739ce2 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -185,18 +185,23 @@ out:
 }
 
 /* Create -kernel TLB entries for BookE, linearly spanning 256MB.  */
+static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
+{
+    return (ffs(size >> 10) - 1) >> 1;
+}
+
 static void mmubooke_create_initial_mapping(CPUState *env,
                                      target_ulong va,
                                      target_phys_addr_t pa)
 {
-    ppcemb_tlb_t *tlb = booke206_get_tlbe(env, 1, 0, 0);
-
-    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;
+    ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 0);
+    target_phys_addr_t size;
+
+    size = (booke206_page_size_to_tlb(256 * 1024 * 1024) << MAS1_TSIZE_SHIFT);
+    tlb->mas1 = MAS1_VALID | size;
+    tlb->mas2 = va & TARGET_PAGE_MASK;
+    tlb->mas7_3 = pa & TARGET_PAGE_MASK;
+    tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX;
 }
 
 static void mpc8544ds_cpu_reset(void *opaque)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 8e4582f..758c554 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -360,9 +360,17 @@ struct ppcemb_tlb_t {
     uint32_t attr; /* Storage attributes */
 };
 
+typedef struct ppcmas_tlb_t {
+     uint32_t mas8;
+     uint32_t mas1;
+     uint64_t mas2;
+     uint64_t mas7_3;
+} ppcmas_tlb_t;
+
 union ppc_tlb_t {
     ppc6xx_tlb_t tlb6;
     ppcemb_tlb_t tlbe;
+    ppcmas_tlb_t tlbm;
 };
 #endif
 
@@ -1075,9 +1083,13 @@ void store_40x_sler (CPUPPCState *env, uint32_t val);
 void store_booke_tcr (CPUPPCState *env, target_ulong val);
 void store_booke_tsr (CPUPPCState *env, target_ulong val);
 void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot);
+target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb);
 int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
                      target_phys_addr_t *raddrp, target_ulong address,
                      uint32_t pid, int ext, int i);
+int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
+                     target_phys_addr_t *raddrp, target_ulong address,
+                     uint32_t pid);
 void ppc_tlb_invalidate_all (CPUPPCState *env);
 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
 #if defined(TARGET_PPC64)
@@ -1927,12 +1939,12 @@ static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static inline int booke206_tlbe_id(CPUState *env, ppcemb_tlb_t *tlbe)
+static inline int booke206_tlbm_id(CPUState *env, ppcmas_tlb_t *tlbm)
 {
-    uintptr_t tlbel = (uintptr_t)tlbe;
+    uintptr_t tlbml = (uintptr_t)tlbm;
     uintptr_t tlbl = (uintptr_t)env->tlb;
 
-    return (tlbel - tlbl) / sizeof(env->tlb[0]);
+    return (tlbml - tlbl) / sizeof(env->tlb[0]);
 }
 
 static inline int booke206_tlb_size(CPUState *env, int tlbn)
@@ -1949,9 +1961,9 @@ static inline int booke206_tlb_ways(CPUState *env, int tlbn)
     return r;
 }
 
-static inline int booke206_tlbe_to_tlbn(CPUState *env, ppcemb_tlb_t *tlbe)
+static inline int booke206_tlbm_to_tlbn(CPUState *env, ppcmas_tlb_t *tlbm)
 {
-    int id = booke206_tlbe_id(env, tlbe);
+    int id = booke206_tlbm_id(env, tlbm);
     int end = 0;
     int i;
 
@@ -1966,14 +1978,14 @@ static inline int booke206_tlbe_to_tlbn(CPUState *env, ppcemb_tlb_t *tlbe)
     return 0;
 }
 
-static inline int booke206_tlbe_to_way(CPUState *env, ppcemb_tlb_t *tlb)
+static inline int booke206_tlbm_to_way(CPUState *env, ppcmas_tlb_t *tlb)
 {
-    int tlbn = booke206_tlbe_to_tlbn(env, tlb);
-    int tlbid = booke206_tlbe_id(env, tlb);
+    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
+    int tlbid = booke206_tlbm_id(env, tlb);
     return tlbid & (booke206_tlb_ways(env, tlbn) - 1);
 }
 
-static inline ppcemb_tlb_t *booke206_get_tlbe(CPUState *env, const int tlbn,
+static inline ppcmas_tlb_t *booke206_get_tlbm(CPUState *env, const int tlbn,
                                               target_ulong ea, int way)
 {
     int r;
@@ -1992,7 +2004,7 @@ static inline ppcemb_tlb_t *booke206_get_tlbe(CPUState *env, const int tlbn,
         r += booke206_tlb_size(env, i);
     }
 
-    return &env->tlb[r].tlbe;
+    return &env->tlb[r].tlbm;
 }
 
 #endif
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 2944b06..8cf9ee1 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1279,8 +1279,8 @@ void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
         if (flags & (1 << i)) {
             tlb_size = booke206_tlb_size(env, i);
             for (j = 0; j < tlb_size; j++) {
-                if (!check_iprot || !(tlb[j].tlbe.attr & MAS1_IPROT)) {
-                    tlb[j].tlbe.prot = 0;
+                if (!check_iprot || !(tlb[j].tlbm.mas1 & MAS1_IPROT)) {
+                    tlb[j].tlbm.mas1 &= ~MAS1_VALID;
                 }
             }
         }
@@ -1290,11 +1290,148 @@ void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
     tlb_flush(env, 1);
 }
 
+target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
+{
+    uint32_t tlbncfg;
+    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
+    target_phys_addr_t tlbm_size;
+
+    tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
+
+    if (tlbncfg & TLBnCFG_AVAIL) {
+        tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+    } else {
+        tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
+    }
+
+    return (1 << (tlbm_size << 1)) << 10;
+}
+
+/* TLB check function for MAS based SoftTLBs */
+int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
+                     target_phys_addr_t *raddrp,
+                     target_ulong address, uint32_t pid)
+{
+    target_ulong mask;
+    uint32_t tlb_pid;
+
+    /* Check valid flag */
+    if (!(tlb->mas1 & MAS1_VALID)) {
+        return -1;
+    }
+
+    mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
+    LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
+              PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
+              __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
+              tlb->mas8);
+
+    /* Check PID */
+    tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
+    if (tlb_pid != 0 && tlb_pid != pid) {
+        return -1;
+    }
+
+    /* Check effective address */
+    if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
+        return -1;
+    }
+    *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
+
+    return 0;
+}
+
+static int mmubooke206_check_tlb(CPUState *env, ppcmas_tlb_t *tlb,
+                                 target_phys_addr_t *raddr, int *prot,
+                                 target_ulong address, int rw,
+                                 int access_type)
+{
+    int ret;
+    int _prot = 0;
+
+    if (ppcmas_tlb_check(env, tlb, raddr, address,
+                         env->spr[SPR_BOOKE_PID]) >= 0) {
+        goto found_tlb;
+    }
+
+    if (env->spr[SPR_BOOKE_PID1] &&
+        ppcmas_tlb_check(env, tlb, raddr, address,
+                         env->spr[SPR_BOOKE_PID1]) >= 0) {
+        goto found_tlb;
+    }
+
+    if (env->spr[SPR_BOOKE_PID2] &&
+        ppcmas_tlb_check(env, tlb, raddr, address,
+                         env->spr[SPR_BOOKE_PID2]) >= 0) {
+        goto found_tlb;
+    }
+
+    LOG_SWTLB("%s: TLB entry not found\n", __func__);
+    return -1;
+
+found_tlb:
+
+    if (msr_pr != 0) {
+        if (tlb->mas7_3 & MAS3_UR) {
+            _prot |= PAGE_READ;
+        }
+        if (tlb->mas7_3 & MAS3_UW) {
+            _prot |= PAGE_WRITE;
+        }
+        if (tlb->mas7_3 & MAS3_UX) {
+            _prot |= PAGE_EXEC;
+        }
+    } else {
+        if (tlb->mas7_3 & MAS3_SR) {
+            _prot |= PAGE_READ;
+        }
+        if (tlb->mas7_3 & MAS3_SW) {
+            _prot |= PAGE_WRITE;
+        }
+        if (tlb->mas7_3 & MAS3_SX) {
+            _prot |= PAGE_EXEC;
+        }
+    }
+
+    /* Check the address space and permissions */
+    if (access_type == ACCESS_CODE) {
+        if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
+            LOG_SWTLB("%s: AS doesn't match\n", __func__);
+            return -1;
+        }
+
+        *prot = _prot;
+        if (_prot & PAGE_EXEC) {
+            LOG_SWTLB("%s: good TLB!\n", __func__);
+            return 0;
+        }
+
+        LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
+        ret = -3;
+    } else {
+        if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
+            LOG_SWTLB("%s: AS doesn't match\n", __func__);
+            return -1;
+        }
+
+        *prot = _prot;
+        if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
+            LOG_SWTLB("%s: found TLB!\n", __func__);
+            return 0;
+        }
+
+        LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
+        ret = -2;
+    }
+
+    return ret;
+}
+
 static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
-                                        target_ulong address, int rw,
-                                        int access_type)
+                                            target_ulong address, int rw,
+                                            int access_type)
 {
-    ppcemb_tlb_t *tlb;
+    ppcmas_tlb_t *tlb;
     target_phys_addr_t raddr;
     int i, j, ret;
 
@@ -1305,9 +1442,9 @@ static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
         int ways = booke206_tlb_ways(env, i);
 
         for (j = 0; j < ways; j++) {
-            tlb = booke206_get_tlbe(env, i, address, j);
-            ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
-                                     access_type, j);
+            tlb = booke206_get_tlbm(env, i, address, j);
+            ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
+                                        rw, access_type);
             if (ret != -1) {
                 goto found_tlb;
             }
@@ -1412,7 +1549,7 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
                                                 rw, access_type);
         } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
             ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
-                                               access_type);
+                                                   access_type);
         } else {
             /* No address translation.  */
             ret = check_physical(env, ctx, eaddr, rw);
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 15d9222..135211d 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -4196,7 +4196,7 @@ target_ulong helper_440_tlbsx (target_ulong address)
 
 /* PowerPC BookE 2.06 TLB management */
 
-static ppcemb_tlb_t *booke206_cur_tlb(CPUState *env)
+static ppcmas_tlb_t *booke206_cur_tlb(CPUState *env)
 {
     uint32_t tlbncfg = 0;
     int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
@@ -4210,17 +4210,7 @@ static ppcemb_tlb_t *booke206_cur_tlb(CPUState *env)
         cpu_abort(env, "we don't support HES yet\n");
     }
 
-    return booke206_get_tlbe(env, tlb, ea, esel);
-}
-
-static inline target_phys_addr_t booke206_tlb_to_page_size(int size)
-{
-    return (1 << (size << 1)) << 10;
-}
-
-static inline target_phys_addr_t booke206_page_size_to_tlb(uint64_t size)
-{
-    return (ffs(size >> 10) - 1) >> 1;
+    return booke206_get_tlbm(env, tlb, ea, esel);
 }
 
 void helper_booke_setpid(uint32_t pidn, target_ulong pid)
@@ -4233,9 +4223,7 @@ void helper_booke_setpid(uint32_t pidn, target_ulong pid)
 void helper_booke206_tlbwe(void)
 {
     uint32_t tlbncfg, tlbn;
-    ppcemb_tlb_t *tlb;
-    target_phys_addr_t rpn;
-    int tlbe_size;
+    ppcmas_tlb_t *tlb;
 
     switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
     case MAS0_WQ_ALWAYS:
@@ -4269,116 +4257,43 @@ void helper_booke206_tlbwe(void)
 
     if (msr_gs) {
         cpu_abort(env, "missing HV implementation\n");
-    } else {
-        rpn = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
-              (env->spr[SPR_BOOKE_MAS3] & 0xfffff000);
-    }
-    tlb->RPN = rpn;
-
-    tlb->PID = (env->spr[SPR_BOOKE_MAS1] & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
-    if (tlbncfg & TLBnCFG_AVAIL) {
-        tlbe_size = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK)
-                    >> MAS1_TSIZE_SHIFT;
-    } else {
-        tlbe_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
     }
+    tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
+                  env->spr[SPR_BOOKE_MAS3];
+    tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
+    /* XXX needs to change when supporting 64-bit e500 */
+    tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & 0xffffffff;
 
-    tlb->size = booke206_tlb_to_page_size(tlbe_size);
-    tlb->EPN = (uint32_t)(env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
-    tlb->attr = env->spr[SPR_BOOKE_MAS2] & (MAS2_ACM | MAS2_VLE | MAS2_W |
-                                            MAS2_I | MAS2_M | MAS2_G | MAS2_E)
-                << 1;
-
-    if (tlbncfg & TLBnCFG_IPROT) {
-        tlb->attr |= env->spr[SPR_BOOKE_MAS1] & MAS1_IPROT;
-    }
-    tlb->attr |= (env->spr[SPR_BOOKE_MAS3] &
-                  ((MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3)) << 8);
-    if (env->spr[SPR_BOOKE_MAS1] & MAS1_TS) {
-        tlb->attr |= 1;
-    }
-
-    tlb->prot = 0;
-
-    if (env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) {
-        tlb->prot |= PAGE_VALID;
-    }
-    if (env->spr[SPR_BOOKE_MAS3] & MAS3_UX) {
-        tlb->prot |= PAGE_EXEC;
-    }
-    if (env->spr[SPR_BOOKE_MAS3] & MAS3_SX) {
-        tlb->prot |= PAGE_EXEC << 4;
-    }
-    if (env->spr[SPR_BOOKE_MAS3] & MAS3_UW) {
-        tlb->prot |= PAGE_WRITE;
-    }
-    if (env->spr[SPR_BOOKE_MAS3] & MAS3_SW) {
-        tlb->prot |= PAGE_WRITE << 4;
-    }
-    if (env->spr[SPR_BOOKE_MAS3] & MAS3_UR) {
-        tlb->prot |= PAGE_READ;
-    }
-    if (env->spr[SPR_BOOKE_MAS3] & MAS3_SR) {
-        tlb->prot |= PAGE_READ << 4;
+    if (!(tlbncfg & TLBnCFG_IPROT)) {
+        /* no IPROT supported by TLB */
+        tlb->mas1 &= ~MAS1_IPROT;
     }
 
-    if (tlb->size == TARGET_PAGE_SIZE) {
-        tlb_flush_page(env, tlb->EPN);
+    if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
+        tlb_flush_page(env, tlb->mas2 & MAS2_EPN_MASK);
     } else {
         tlb_flush(env, 1);
     }
 }
 
-static inline void booke206_tlb_to_mas(CPUState *env, ppcemb_tlb_t *tlb)
+static inline void booke206_tlb_to_mas(CPUState *env, ppcmas_tlb_t *tlb)
 {
-    int tlbn = booke206_tlbe_to_tlbn(env, tlb);
-    int way = booke206_tlbe_to_way(env, tlb);
+    int tlbn = booke206_tlbm_to_tlbn(env, tlb);
+    int way = booke206_tlbm_to_way(env, tlb);
 
     env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
     env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
-
-    env->spr[SPR_BOOKE_MAS1] = MAS1_VALID;
-    env->spr[SPR_BOOKE_MAS2] = 0;
-
-    env->spr[SPR_BOOKE_MAS7] = (uint64_t)tlb->RPN >> 32;
-    env->spr[SPR_BOOKE_MAS3] = tlb->RPN;
-    env->spr[SPR_BOOKE_MAS1] |= tlb->PID << MAS1_TID_SHIFT;
-    env->spr[SPR_BOOKE_MAS1] |= booke206_page_size_to_tlb(tlb->size)
-                                << MAS1_TSIZE_SHIFT;
-    env->spr[SPR_BOOKE_MAS1] |= tlb->attr & MAS1_IPROT;
-    if (tlb->attr & 1) {
-        env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
-    }
-
-    env->spr[SPR_BOOKE_MAS2] = tlb->EPN;
-    env->spr[SPR_BOOKE_MAS2] |= (tlb->attr >> 1) &
-        (MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E);
-
-    if (tlb->prot & PAGE_EXEC) {
-        env->spr[SPR_BOOKE_MAS3] |= MAS3_UX;
-    }
-    if (tlb->prot & (PAGE_EXEC << 4)) {
-        env->spr[SPR_BOOKE_MAS3] |= MAS3_SX;
-    }
-    if (tlb->prot & PAGE_WRITE) {
-        env->spr[SPR_BOOKE_MAS3] |= MAS3_UW;
-    }
-    if (tlb->prot & (PAGE_WRITE << 4)) {
-        env->spr[SPR_BOOKE_MAS3] |= MAS3_SW;
-    }
-    if (tlb->prot & PAGE_READ) {
-        env->spr[SPR_BOOKE_MAS3] |= MAS3_UR;
-    }
-    if (tlb->prot & (PAGE_READ << 4)) {
-        env->spr[SPR_BOOKE_MAS3] |= MAS3_SR;
-    }
-
     env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
+
+    env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
+    env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
+    env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
+    env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
 }
 
 void helper_booke206_tlbre(void)
 {
-    ppcemb_tlb_t *tlb = NULL;
+    ppcmas_tlb_t *tlb = NULL;
 
     tlb = booke206_cur_tlb(env);
     booke206_tlb_to_mas(env, tlb);
@@ -4386,7 +4301,7 @@ void helper_booke206_tlbre(void)
 
 void helper_booke206_tlbsx(target_ulong address)
 {
-    ppcemb_tlb_t *tlb = NULL;
+    ppcmas_tlb_t *tlb = NULL;
     int i, j;
     target_phys_addr_t raddr;
     uint32_t spid, sas;
@@ -4398,13 +4313,13 @@ void helper_booke206_tlbsx(target_ulong address)
         int ways = booke206_tlb_ways(env, i);
 
         for (j = 0; j < ways; j++) {
-            tlb = booke206_get_tlbe(env, i, address, j);
+            tlb = booke206_get_tlbm(env, i, address, j);
 
-            if (ppcemb_tlb_check(env, tlb, &raddr, address, spid, 0, j)) {
+            if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
                 continue;
             }
 
-            if (sas != (tlb->attr & MAS6_SAS)) {
+            if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
                 continue;
             }
 
@@ -4439,13 +4354,14 @@ static inline void booke206_invalidate_ea_tlb(CPUState *env, int tlbn,
 {
     int i;
     int ways = booke206_tlb_ways(env, tlbn);
+    target_ulong mask;
 
     for (i = 0; i < ways; i++) {
-        ppcemb_tlb_t *tlb = booke206_get_tlbe(env, tlbn, ea, i);
-        target_phys_addr_t masked_ea = ea & ~(tlb->size - 1);
-        if ((tlb->EPN == (masked_ea >> MAS2_EPN_SHIFT)) &&
-            !(tlb->attr & MAS1_IPROT)) {
-            tlb->prot = 0;
+        ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
+        mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
+        if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
+            !(tlb->mas1 & MAS1_IPROT)) {
+            tlb->mas1 &= ~MAS1_VALID;
         }
     }
 }
commit 8018dc63aab936f1a5cff6e707289116ea97c423
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jun 16 10:44:23 2011 +0200

    PPC: Only set lower 32bits with mtmsr
    
    As Nathan pointed out correctly, the mtmsr instruction does not modify
    the high 32 bits of MSR. It also doesn't matter if SF is set or not,
    the instruction always behaves the same.
    
    This patch moves it a bit closer to the spec.
    
    Reported-by: Nathan Whitehorn <nwhitehorn at freebsd.org>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 59aef85..7e318e3 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3878,24 +3878,19 @@ static void gen_mtmsr(DisasContext *ctx)
         tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
         tcg_temp_free(t0);
     } else {
+        TCGv msr = tcg_temp_new();
+
         /* XXX: we need to update nip before the store
          *      if we enter power saving mode, we will exit the loop
          *      directly from ppc_store_msr
          */
         gen_update_nip(ctx, ctx->nip);
 #if defined(TARGET_PPC64)
-        if (!ctx->sf_mode) {
-            TCGv t0 = tcg_temp_new();
-            TCGv t1 = tcg_temp_new();
-            tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
-            tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
-            tcg_gen_or_tl(t0, t0, t1);
-            tcg_temp_free(t1);
-            gen_helper_store_msr(t0);
-            tcg_temp_free(t0);
-        } else
+        tcg_gen_deposit_tl(msr, cpu_msr, cpu_gpr[rS(ctx->opcode)], 0, 32);
+#else
+        tcg_gen_mov_tl(msr, cpu_gpr[rS(ctx->opcode)]);
 #endif
-            gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
+        gen_helper_store_msr(msr);
         /* Must stop the translation as machine state (may have) changed */
         /* Note that mtmsr is not always defined as context-synchronizing */
         gen_stop_exception(ctx);
commit a59106cbbb53917352b3e76c5551b65432878e19
Author: Alexander Graf <agraf at suse.de>
Date:   Fri Jun 17 02:56:56 2011 +0200

    PPC: update openbios firmware
    
    There were some changes upstream to account for broken usage of mtmsr, so
    before applying the mtmsr patch we need to update OpenBIOS, otherwise the
    PPC target would break.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/pc-bios/README b/pc-bios/README
index fe221a9..40568f8 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -10,8 +10,10 @@
 - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
-  The included image for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32
-  and Sparc64 are built from OpenBIOS SVN revision 1018.
+  The included image for PowerPC (for 32 and 64 bit PPC CPUs),
+
+  PowerPC is built from OpenBIOS SVN revision 1044
+  Sparc32 and Sparc64 are built from OpenBIOS SVN revision 1018.
 
 - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
   implementation for certain IBM POWER hardware.  The sources are at
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index ee6f5ae..6525a91 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
commit 5de6b46db51cb34857c8bfaef355e048fbc6e020
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Jun 15 23:34:04 2011 +0200

    PPC: mpc8544ds: Add hypervisor node
    
    When running a PPC guest with KVM that can do PV operations, we need
    to indicate the guest which instructions to use for a hypercall and
    that it is running as KVM guest.
    
    This logic was available on openbios based machines already. This patch
    also adds said functionality to the mpc8544ds machine.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Acked-by: Scott Wood <scottwood at freescale.com>

diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 3ba8e75..073de3c 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -82,11 +82,12 @@ out:
 }
 #endif
 
-static int mpc8544_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)
+static int mpc8544_load_device_tree(CPUState *env,
+                                    target_phys_addr_t addr,
+                                    uint32_t ramsize,
+                                    target_phys_addr_t initrd_base,
+                                    target_phys_addr_t initrd_size,
+                                    const char *kernel_cmdline)
 {
     int ret = -1;
 #ifdef CONFIG_FDT
@@ -94,6 +95,7 @@ static int mpc8544_load_device_tree(target_phys_addr_t addr,
     char *filename;
     int fdt_size;
     void *fdt;
+    uint8_t hypercall[16];
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
     if (!filename) {
@@ -157,6 +159,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");
+
+        /* indicate KVM hypercall interface */
+        qemu_devtree_setprop_string(fdt, "/hypervisor", "compatible",
+                                    "linux,kvm");
+        kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
+        qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
+                             hypercall, sizeof(hypercall));
     } else {
         const uint32_t freq = 400000000;
 
@@ -330,7 +339,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
         cpu_abort(env, "Compiled without FDT support - can't load kernel\n");
 #endif
         dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
-        if (mpc8544_load_device_tree(dt_base, ram_size,
+        if (mpc8544_load_device_tree(env, dt_base, ram_size,
                     initrd_base, initrd_size, kernel_cmdline) < 0) {
             fprintf(stderr, "couldn't load device tree\n");
             exit(1);
diff --git a/pc-bios/mpc8544ds.dtb b/pc-bios/mpc8544ds.dtb
index 189224e..ae318b1 100644
Binary files a/pc-bios/mpc8544ds.dtb and b/pc-bios/mpc8544ds.dtb differ
diff --git a/pc-bios/mpc8544ds.dts b/pc-bios/mpc8544ds.dts
index fd792d5..a88b47c 100644
--- a/pc-bios/mpc8544ds.dts
+++ b/pc-bios/mpc8544ds.dts
@@ -125,4 +125,7 @@
 	chosen {
 		linux,stdout-path = "/soc8544 at e0000000/serial at 4500";
 	};
+
+	hypervisor {
+	};
 };
commit b9e17a345382ebb91446fd6cf0bb8f0eb5ba5706
Author: Alexander Graf <agraf at suse.de>
Date:   Wed Jun 15 23:27:19 2011 +0200

    PPC: calculate kernel,initrd,cmdline locations dynamically
    
    During testing, I was generating a vmlinux binary that easily occupied
    more than 20MB of RAM. Since the current -kernel code loads the initrd
    at a fixed address behind the kernel, we were overwriting kernel data
    when the kernel got too big.
    
    To finally get rid of the issue, let's calculate the initrd and cmdline
    addresses relative to the kernel size, so we can have kernels and initrds
    that are as big as they want to - as long as they fit in RAM.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index ea87593..68dade7 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -35,8 +35,7 @@
 #define PROM_ADDR         0xfff00000
 
 #define KERNEL_LOAD_ADDR 0x01000000
-#define CMDLINE_ADDR     0x027ff000
-#define INITRD_LOAD_ADDR 0x02800000
+#define KERNEL_GAP       0x00100000
 
 #define ESCC_CLOCK 3686400
 
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 86f1cfb..5bce709 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -120,6 +120,11 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
 }
 
+static target_phys_addr_t round_page(target_phys_addr_t addr)
+{
+    return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+}
+
 /* PowerPC Mac99 hardware initialisation */
 static void ppc_core99_init (ram_addr_t ram_size,
                              const char *boot_device,
@@ -134,7 +139,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
     int unin_memory;
     int linux_boot, i;
     ram_addr_t ram_offset, bios_offset;
-    uint32_t kernel_base, initrd_base;
+    target_phys_addr_t kernel_base, initrd_base, cmdline_base = 0;
     long kernel_size, initrd_size;
     PCIBus *pci_bus;
     MacIONVRAMState *nvr;
@@ -220,7 +225,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
         }
         /* load initrd */
         if (initrd_filename) {
-            initrd_base = INITRD_LOAD_ADDR;
+            initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
             initrd_size = load_image_targphys(initrd_filename, initrd_base,
                                               ram_size - initrd_base);
             if (initrd_size < 0) {
@@ -228,9 +233,11 @@ static void ppc_core99_init (ram_addr_t ram_size,
                          initrd_filename);
                 exit(1);
             }
+            cmdline_base = round_page(initrd_base + initrd_size);
         } else {
             initrd_base = 0;
             initrd_size = 0;
+            cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
         }
         ppc_boot_device = 'm';
     } else {
@@ -373,8 +380,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
     if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
+        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
     } else {
         fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
     }
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 75a3127..20cd8e1 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -59,6 +59,11 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
 }
 
+static target_phys_addr_t round_page(target_phys_addr_t addr)
+{
+    return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+}
+
 static void ppc_heathrow_init (ram_addr_t ram_size,
                                const char *boot_device,
                                const char *kernel_filename,
@@ -71,7 +76,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     qemu_irq *pic, **heathrow_irqs;
     int linux_boot, i;
     ram_addr_t ram_offset, bios_offset;
-    uint32_t kernel_base, initrd_base;
+    uint32_t kernel_base, initrd_base, cmdline_base = 0;
     int32_t kernel_size, initrd_size;
     PCIBus *pci_bus;
     MacIONVRAMState *nvr;
@@ -157,7 +162,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         }
         /* load initrd */
         if (initrd_filename) {
-            initrd_base = INITRD_LOAD_ADDR;
+            initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
             initrd_size = load_image_targphys(initrd_filename, initrd_base,
                                               ram_size - initrd_base);
             if (initrd_size < 0) {
@@ -165,9 +170,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
                          initrd_filename);
                 exit(1);
             }
+            cmdline_base = round_page(initrd_base + initrd_size);
         } else {
             initrd_base = 0;
             initrd_size = 0;
+            cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
         }
         ppc_boot_device = 'm';
     } else {
@@ -278,8 +285,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
     fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
     if (kernel_cmdline) {
-        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
-        pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
+        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
     } else {
         fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
     }
commit 826e7b827c5f83e88d5aa84c0bf0b3459f28ec35
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Tue Jun 14 23:27:56 2011 +0200

    target-ppc: Handle memory-forced I/O controller access
    
    On at least the PowerPC 601, a direct-store (T=1) with bus unit ID 0x07F
    is special-cased as memory-forced I/O controller access. It is supposed
    to be checked immediately if T=1, bypassing all protection mechanisms
    and acting cache-inhibited and global.
    
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    
    Simplified by avoiding reindentation. Added explanatory comments.
    
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index cf2a368..2944b06 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -949,8 +949,24 @@ static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
             ret = -3;
         }
     } else {
+        target_ulong sr;
         LOG_MMU("direct store...\n");
         /* Direct-store segment : absolutely *BUGGY* for now */
+
+        /* Direct-store implies a 32-bit MMU.
+         * Check the Segment Register's bus unit ID (BUID).
+         */
+        sr = env->sr[eaddr >> 28];
+        if ((sr & 0x1FF00000) >> 20 == 0x07f) {
+            /* Memory-forced I/O controller interface access */
+            /* If T=1 and BUID=x'07F', the 601 performs a memory access
+             * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
+             */
+            ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
+            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+            return 0;
+        }
+
         switch (type) {
         case ACCESS_INT:
             /* Integer load/store : only access allowed */
commit b0fb84236da4a36a852010b6b5d5d3ca497a2b68
Author: Alexander Graf <agraf at suse.de>
Date:   Thu Jun 2 13:53:40 2011 +0200

    PPC: E500: Implement reboot controller
    
    When Linux reboots an e500 VM, it writes to a magic register in the
    "global-utilities" device indicated by the device tree. We were not
    emulating that device so far, rendering the VM reboot-less.
    
    This patch implements that device with only the reboot functionality
    implemented and adds it to the device tree. With this patch applied,
    I can successfully reboot a -M mpc8544ds VM.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Reviewed-by: Andreas Färber <andreas.faerber at web.de>

diff --git a/Makefile.target b/Makefile.target
index b1a0f6d..d3ebe57 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -256,7 +256,7 @@ endif
 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
+obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o
 # PowerPC 440 Xilinx ML507 reference board.
 obj-ppc-y += virtex_ml507.o
 obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
new file mode 100644
index 0000000..c685f3e
--- /dev/null
+++ b/hw/mpc8544_guts.c
@@ -0,0 +1,135 @@
+/*
+ * QEMU PowerPC MPC8544 global util pseudo-device
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Alexander Graf, <alex at csgraf.de>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of  the GNU General  Public License as published by
+ * the Free Software Foundation;  either version 2 of the  License, or
+ * (at your option) any later version.
+ *
+ * *****************************************************************
+ *
+ * The documentation for this device is noted in the MPC8544 documentation,
+ * file name "MPC8544ERM.pdf". You can easily find it on the web.
+ *
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "sysbus.h"
+
+#define MPC8544_GUTS_MMIO_SIZE        0x1000
+#define MPC8544_GUTS_RSTCR_RESET      0x02
+
+#define MPC8544_GUTS_ADDR_PORPLLSR    0x00
+#define MPC8544_GUTS_ADDR_PORBMSR     0x04
+#define MPC8544_GUTS_ADDR_PORIMPSCR   0x08
+#define MPC8544_GUTS_ADDR_PORDEVSR    0x0C
+#define MPC8544_GUTS_ADDR_PORDBGMSR   0x10
+#define MPC8544_GUTS_ADDR_PORDEVSR2   0x14
+#define MPC8544_GUTS_ADDR_GPPORCR     0x20
+#define MPC8544_GUTS_ADDR_GPIOCR      0x30
+#define MPC8544_GUTS_ADDR_GPOUTDR     0x40
+#define MPC8544_GUTS_ADDR_GPINDR      0x50
+#define MPC8544_GUTS_ADDR_PMUXCR      0x60
+#define MPC8544_GUTS_ADDR_DEVDISR     0x70
+#define MPC8544_GUTS_ADDR_POWMGTCSR   0x80
+#define MPC8544_GUTS_ADDR_MCPSUMR     0x90
+#define MPC8544_GUTS_ADDR_RSTRSCR     0x94
+#define MPC8544_GUTS_ADDR_PVR         0xA0
+#define MPC8544_GUTS_ADDR_SVR         0xA4
+#define MPC8544_GUTS_ADDR_RSTCR       0xB0
+#define MPC8544_GUTS_ADDR_IOVSELSR    0xC0
+#define MPC8544_GUTS_ADDR_DDRCSR      0xB20
+#define MPC8544_GUTS_ADDR_DDRCDR      0xB24
+#define MPC8544_GUTS_ADDR_DDRCLKDR    0xB28
+#define MPC8544_GUTS_ADDR_CLKOCR      0xE00
+#define MPC8544_GUTS_ADDR_SRDS1CR1    0xF04
+#define MPC8544_GUTS_ADDR_SRDS2CR1    0xF10
+#define MPC8544_GUTS_ADDR_SRDS2CR3    0xF18
+
+struct GutsState {
+    SysBusDevice busdev;
+};
+
+typedef struct GutsState GutsState;
+
+static uint32_t mpc8544_guts_read32(void *opaque, target_phys_addr_t addr)
+{
+    uint32_t value = 0;
+    CPUState *env = cpu_single_env;
+
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_PVR:
+        value = env->spr[SPR_PVR];
+        break;
+    case MPC8544_GUTS_ADDR_SVR:
+        value = env->spr[SPR_E500_SVR];
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr);
+        break;
+    }
+
+    return value;
+}
+
+static CPUReadMemoryFunc * const mpc8544_guts_read[] = {
+    NULL,
+    NULL,
+    &mpc8544_guts_read32,
+};
+
+static void mpc8544_guts_write32(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    addr &= MPC8544_GUTS_MMIO_SIZE - 1;
+
+    switch (addr) {
+    case MPC8544_GUTS_ADDR_RSTCR:
+        if (value & MPC8544_GUTS_RSTCR_RESET) {
+            qemu_system_reset_request();
+        }
+        break;
+    default:
+        fprintf(stderr, "guts: Unknown register write: %x = %x\n",
+                (int)addr, value);
+        break;
+    }
+}
+
+static CPUWriteMemoryFunc * const mpc8544_guts_write[] = {
+    NULL,
+    NULL,
+    &mpc8544_guts_write32,
+};
+
+static int mpc8544_guts_initfn(SysBusDevice *dev)
+{
+    GutsState *s;
+    int iomem;
+
+    s = FROM_SYSBUS(GutsState, sysbus_from_qdev(dev));
+
+    iomem = cpu_register_io_memory(mpc8544_guts_read, mpc8544_guts_write, s,
+                                   DEVICE_BIG_ENDIAN);
+    sysbus_init_mmio(dev, MPC8544_GUTS_MMIO_SIZE, iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo mpc8544_guts_info = {
+    .init         = mpc8544_guts_initfn,
+    .qdev.name    = "mpc8544-guts",
+    .qdev.size    = sizeof(GutsState),
+};
+
+static void mpc8544_guts_register(void)
+{
+    sysbus_register_withprop(&mpc8544_guts_info);
+}
+device_init(mpc8544_guts_register);
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 6b57fbf..3ba8e75 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -50,6 +50,7 @@
 #define MPC8544_PCI_REGS_SIZE      0x1000
 #define MPC8544_PCI_IO             0xE1000000
 #define MPC8544_PCI_IOLEN          0x10000
+#define MPC8544_UTIL_BASE          (MPC8544_CCSRBAR_BASE + 0xe0000)
 
 struct boot_info
 {
@@ -270,6 +271,9 @@ static void mpc8544ds_init(ram_addr_t ram_size,
                        serial_hds[0], 1, 1);
     }
 
+    /* General Utility device */
+    sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);
+
     /* PCI */
     dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
                                 mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
diff --git a/pc-bios/mpc8544ds.dtb b/pc-bios/mpc8544ds.dtb
index 3299546..189224e 100644
Binary files a/pc-bios/mpc8544ds.dtb and b/pc-bios/mpc8544ds.dtb differ
diff --git a/pc-bios/mpc8544ds.dts b/pc-bios/mpc8544ds.dts
index 872152d..fd792d5 100644
--- a/pc-bios/mpc8544ds.dts
+++ b/pc-bios/mpc8544ds.dts
@@ -82,6 +82,12 @@
 			compatible = "chrp,open-pic";
 			device_type = "open-pic";
 		};
+
+                global-utilities at e0000 {        //global utilities block
+                        compatible = "fsl,mpc8544-guts";
+                        reg = <0xe0000 0x1000>;
+                        fsl,has-rstcr;
+                };
 	};
 
 	pci0: pci at e0008000 {


More information about the Spice-commits mailing list