All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation
@ 2016-06-22  6:52 Richard Henderson
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 1/3] tcg: Fix name for high-half register Richard Henderson
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Richard Henderson @ 2016-06-22  6:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien, thuth

Attempting to fix the problem reported by Mark re i686 vs sparc64.

Unsurprisingly, the problems tend to revolve around the 6 operand
opcodes like sub2 or qemu_st64, where we use all, or all but one
register.


r~


Richard Henderson (3):
  tcg: Fix name for high-half register
  tcg: Optimize spills of constants
  tcg: Rearrange register allocation

 tcg/aarch64/tcg-target.inc.c |  10 ++
 tcg/arm/tcg-target.inc.c     |   6 +
 tcg/i386/tcg-target.inc.c    |  21 ++-
 tcg/ia64/tcg-target.inc.c    |  10 ++
 tcg/mips/tcg-target.inc.c    |  10 ++
 tcg/ppc/tcg-target.inc.c     |   6 +
 tcg/s390/tcg-target.inc.c    |   6 +
 tcg/sparc/tcg-target.inc.c   |  10 ++
 tcg/tcg.c                    | 409 +++++++++++++++++++++++++++++--------------
 tcg/tci/tcg-target.inc.c     |   6 +
 10 files changed, 351 insertions(+), 143 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v2 1/3] tcg: Fix name for high-half register
  2016-06-22  6:52 [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation Richard Henderson
@ 2016-06-22  6:52 ` Richard Henderson
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 2/3] tcg: Optimize spills of constants Richard Henderson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2016-06-22  6:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien, thuth

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 254427b..154ffe8 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -557,7 +557,7 @@ int tcg_global_mem_new_internal(TCGType type, TCGv_ptr base,
         ts2->mem_offset = offset + (1 - bigendian) * 4;
         pstrcpy(buf, sizeof(buf), name);
         pstrcat(buf, sizeof(buf), "_1");
-        ts->name = strdup(buf);
+        ts2->name = strdup(buf);
     } else {
         ts->base_type = type;
         ts->type = type;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v2 2/3] tcg: Optimize spills of constants
  2016-06-22  6:52 [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation Richard Henderson
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 1/3] tcg: Fix name for high-half register Richard Henderson
@ 2016-06-22  6:52 ` Richard Henderson
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 3/3] tcg: Rearrange register allocation Richard Henderson
  2016-06-22 19:00 ` [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc " Mark Cave-Ayland
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2016-06-22  6:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien, thuth

While we can store constants via constrants on INDEX_op_st_i32 et al,
we weren't able to spill constants to backing store.

Add a new backend interface, tcg_out_sti, which may store the constant
(and is allowed to fail).  Rearrange the temp_* helpers so that we only
attempt to directly store a constant when the temp is becoming dead/free.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/aarch64/tcg-target.inc.c |  10 +++
 tcg/arm/tcg-target.inc.c     |   6 ++
 tcg/i386/tcg-target.inc.c    |  21 ++++--
 tcg/ia64/tcg-target.inc.c    |  10 +++
 tcg/mips/tcg-target.inc.c    |  10 +++
 tcg/ppc/tcg-target.inc.c     |   6 ++
 tcg/s390/tcg-target.inc.c    |   6 ++
 tcg/sparc/tcg-target.inc.c   |  10 +++
 tcg/tcg.c                    | 159 ++++++++++++++++++++++++-------------------
 tcg/tci/tcg-target.inc.c     |   6 ++
 10 files changed, 166 insertions(+), 78 deletions(-)

diff --git a/tcg/aarch64/tcg-target.inc.c b/tcg/aarch64/tcg-target.inc.c
index 1447f7c..5ac0091 100644
--- a/tcg/aarch64/tcg-target.inc.c
+++ b/tcg/aarch64/tcg-target.inc.c
@@ -716,6 +716,16 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
                  arg, arg1, arg2);
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    if (val == 0) {
+        tcg_out_st(s, type, TCG_REG_XZR, base, ofs);
+        return true;
+    }
+    return false;
+}
+
 static inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
                                TCGReg rn, unsigned int a, unsigned int b)
 {
diff --git a/tcg/arm/tcg-target.inc.c b/tcg/arm/tcg-target.inc.c
index f9f54c6..172feba 100644
--- a/tcg/arm/tcg-target.inc.c
+++ b/tcg/arm/tcg-target.inc.c
@@ -2046,6 +2046,12 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
     tcg_out_st32(s, COND_AL, arg, arg1, arg2);
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    return false;
+}
+
 static inline void tcg_out_mov(TCGContext *s, TCGType type,
                                TCGReg ret, TCGReg arg)
 {
diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c
index 317484c..bc34535 100644
--- a/tcg/i386/tcg-target.inc.c
+++ b/tcg/i386/tcg-target.inc.c
@@ -710,12 +710,19 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
     tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
 }
 
-static inline void tcg_out_sti(TCGContext *s, TCGType type, TCGReg base,
-                               tcg_target_long ofs, tcg_target_long val)
+static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                        TCGReg base, intptr_t ofs)
 {
-    int opc = OPC_MOVL_EvIz + (type == TCG_TYPE_I64 ? P_REXW : 0);
-    tcg_out_modrm_offset(s, opc, 0, base, ofs);
+    int rexw = 0;
+    if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64) {
+        if (val != (int32_t)val) {
+            return false;
+        }
+        rexw = P_REXW;
+    }
+    tcg_out_modrm_offset(s, OPC_MOVL_EvIz | rexw, 0, base, ofs);
     tcg_out32(s, val);
+    return true;
 }
 
 static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
@@ -1321,10 +1328,10 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
             ofs += 4;
         }
 
-        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, oi);
+        tcg_out_sti(s, TCG_TYPE_I32, oi, TCG_REG_ESP, ofs);
         ofs += 4;
 
-        tcg_out_sti(s, TCG_TYPE_PTR, TCG_REG_ESP, ofs, (uintptr_t)l->raddr);
+        tcg_out_sti(s, TCG_TYPE_PTR, (uintptr_t)l->raddr, TCG_REG_ESP, ofs);
     } else {
         tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
         /* The second argument is already loaded with addrlo.  */
@@ -1413,7 +1420,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
             ofs += 4;
         }
 
-        tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, oi);
+        tcg_out_sti(s, TCG_TYPE_I32, oi, TCG_REG_ESP, ofs);
         ofs += 4;
 
         retaddr = TCG_REG_EAX;
diff --git a/tcg/ia64/tcg-target.inc.c b/tcg/ia64/tcg-target.inc.c
index 395223e..c91f392 100644
--- a/tcg/ia64/tcg-target.inc.c
+++ b/tcg/ia64/tcg-target.inc.c
@@ -973,6 +973,16 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
     }
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    if (val == 0) {
+        tcg_out_st(s, type, TCG_REG_R0, base, ofs);
+        return true;
+    }
+    return false;
+}
+
 static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, uint64_t opc_a3,
                                TCGReg ret, TCGArg arg1, int const_arg1,
                                TCGArg arg2, int const_arg2)
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 50e98ea..2f9be48 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -576,6 +576,16 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
     tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    if (val == 0) {
+        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
+        return true;
+    }
+    return false;
+}
+
 static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
 {
     if (val == (int16_t)val) {
diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c
index da10052..dba954c 100644
--- a/tcg/ppc/tcg-target.inc.c
+++ b/tcg/ppc/tcg-target.inc.c
@@ -857,6 +857,12 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
     tcg_out_mem_long(s, opi, opx, arg, arg1, arg2);
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    return false;
+}
+
 static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
                         int const_arg2, int cr, TCGType type)
 {
diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c
index e0a60e6..314c183 100644
--- a/tcg/s390/tcg-target.inc.c
+++ b/tcg/s390/tcg-target.inc.c
@@ -798,6 +798,12 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
     }
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    return false;
+}
+
 /* load data from an absolute host address */
 static void tcg_out_ld_abs(TCGContext *s, TCGType type, TCGReg dest, void *abs)
 {
diff --git a/tcg/sparc/tcg-target.inc.c b/tcg/sparc/tcg-target.inc.c
index 9938a50..8e98172 100644
--- a/tcg/sparc/tcg-target.inc.c
+++ b/tcg/sparc/tcg-target.inc.c
@@ -504,6 +504,16 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
     tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    if (val == 0) {
+        tcg_out_st(s, type, TCG_REG_G0, base, ofs);
+        return true;
+    }
+    return false;
+}
+
 static void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, uintptr_t arg)
 {
     tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 154ffe8..44de991 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -108,6 +108,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
                        const int *const_args);
 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
                        intptr_t arg2);
+static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                        TCGReg base, intptr_t ofs);
 static void tcg_out_call(TCGContext *s, tcg_insn_unit *target);
 static int tcg_target_const_match(tcg_target_long val, TCGType type,
                                   const TCGArgConstraint *arg_ct);
@@ -1680,35 +1682,89 @@ static void temp_allocate_frame(TCGContext *s, int temp)
 
 static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet);
 
-/* sync register 'reg' by saving it to the corresponding temporary */
-static void tcg_reg_sync(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
+/* Mark a temporary as free or dead.  If 'free_or_dead' is negative,
+   mark it free; otherwise mark it dead.  */
+static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
 {
-    TCGTemp *ts = s->reg_to_temp[reg];
+    if (ts->fixed_reg) {
+        return;
+    }
+    if (ts->val_type == TEMP_VAL_REG) {
+        s->reg_to_temp[ts->reg] = NULL;
+    }
+    ts->val_type = (free_or_dead < 0
+                    || ts->temp_local
+                    || temp_idx(s, ts) < s->nb_globals
+                    ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
+}
 
-    tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
-    if (!ts->mem_coherent && !ts->fixed_reg) {
+/* Mark a temporary as dead.  */
+static inline void temp_dead(TCGContext *s, TCGTemp *ts)
+{
+    temp_free_or_dead(s, ts, 1);
+}
+
+/* Sync a temporary to memory. 'allocated_regs' is used in case a temporary
+   registers needs to be allocated to store a constant.  If 'free_or_dead'
+   is non-zero, subsequently release the temporary; if it is positive, the
+   temp is dead; if it is negative, the temp is free.  */
+static void temp_sync(TCGContext *s, TCGTemp *ts,
+                      TCGRegSet allocated_regs, int free_or_dead)
+{
+    if (ts->fixed_reg) {
+        return;
+    }
+    if (!ts->mem_coherent) {
         if (!ts->mem_allocated) {
             temp_allocate_frame(s, temp_idx(s, ts));
-        } else if (ts->indirect_reg) {
-            tcg_regset_set_reg(allocated_regs, ts->reg);
+        }
+        if (ts->indirect_reg) {
+            if (ts->val_type == TEMP_VAL_REG) {
+                tcg_regset_set_reg(allocated_regs, ts->reg);
+            }
             temp_load(s, ts->mem_base,
                       tcg_target_available_regs[TCG_TYPE_PTR],
                       allocated_regs);
         }
-        tcg_out_st(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
+        switch (ts->val_type) {
+        case TEMP_VAL_CONST:
+            /* If we're going to free the temp immediately, then we won't
+               require it later in a register, so attempt to store the
+               constant to memory directly.  */
+            if (free_or_dead
+                && tcg_out_sti(s, ts->type, ts->val,
+                               ts->mem_base->reg, ts->mem_offset)) {
+                break;
+            }
+            temp_load(s, ts, tcg_target_available_regs[ts->type],
+                      allocated_regs);
+            /* fallthrough */
+
+        case TEMP_VAL_REG:
+            tcg_out_st(s, ts->type, ts->reg,
+                       ts->mem_base->reg, ts->mem_offset);
+            break;
+
+        case TEMP_VAL_MEM:
+            break;
+
+        case TEMP_VAL_DEAD:
+        default:
+            tcg_abort();
+        }
+        ts->mem_coherent = 1;
+    }
+    if (free_or_dead) {
+        temp_free_or_dead(s, ts, free_or_dead);
     }
-    ts->mem_coherent = 1;
 }
 
 /* free register 'reg' by spilling the corresponding temporary if necessary */
 static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
 {
     TCGTemp *ts = s->reg_to_temp[reg];
-
     if (ts != NULL) {
-        tcg_reg_sync(s, reg, allocated_regs);
-        ts->val_type = TEMP_VAL_MEM;
-        s->reg_to_temp[reg] = NULL;
+        temp_sync(s, ts, allocated_regs, -1);
     }
 }
 
@@ -1756,7 +1812,6 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
     case TEMP_VAL_CONST:
         reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
         tcg_out_movi(s, ts->type, reg, ts->val);
-        ts->mem_coherent = 0;
         break;
     case TEMP_VAL_MEM:
         reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
@@ -1778,41 +1833,6 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
     s->reg_to_temp[reg] = ts;
 }
 
-/* mark a temporary as dead. */
-static inline void temp_dead(TCGContext *s, TCGTemp *ts)
-{
-    if (ts->fixed_reg) {
-        return;
-    }
-    if (ts->val_type == TEMP_VAL_REG) {
-        s->reg_to_temp[ts->reg] = NULL;
-    }
-    ts->val_type = (temp_idx(s, ts) < s->nb_globals || ts->temp_local
-                    ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
-}
-
-/* sync a temporary to memory. 'allocated_regs' is used in case a
-   temporary registers needs to be allocated to store a constant. */
-static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
-{
-    if (ts->fixed_reg) {
-        return;
-    }
-    switch (ts->val_type) {
-    case TEMP_VAL_CONST:
-        temp_load(s, ts, tcg_target_available_regs[ts->type], allocated_regs);
-        /* fallthrough */
-    case TEMP_VAL_REG:
-        tcg_reg_sync(s, ts->reg, allocated_regs);
-        break;
-    case TEMP_VAL_DEAD:
-    case TEMP_VAL_MEM:
-        break;
-    default:
-        tcg_abort();
-    }
-}
-
 /* save a temporary to memory. 'allocated_regs' is used in case a
    temporary registers needs to be allocated to store a constant. */
 static inline void temp_save(TCGContext *s, TCGTemp *ts,
@@ -1827,8 +1847,7 @@ static inline void temp_save(TCGContext *s, TCGTemp *ts,
         return;
     }
 #endif
-    temp_sync(s, ts, allocated_regs);
-    temp_dead(s, ts);
+    temp_sync(s, ts, allocated_regs, 1);
 }
 
 /* save globals to their canonical location and assume they can be
@@ -1861,7 +1880,7 @@ static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
             continue;
         }
 #endif
-        temp_sync(s, ts, allocated_regs);
+        temp_sync(s, ts, allocated_regs, 0);
     }
 }
 
@@ -1905,21 +1924,21 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
     val = args[1];
 
     if (ots->fixed_reg) {
-        /* for fixed registers, we do not do any constant
-           propagation */
+        /* For fixed registers, we do not do any constant propagation.  */
         tcg_out_movi(s, ots->type, ots->reg, val);
-    } else {
-        /* The movi is not explicitly generated here */
-        if (ots->val_type == TEMP_VAL_REG) {
-            s->reg_to_temp[ots->reg] = NULL;
-        }
-        ots->val_type = TEMP_VAL_CONST;
-        ots->val = val;
+        return;
     }
-    if (NEED_SYNC_ARG(0)) {
-        temp_sync(s, ots, s->reserved_regs);
+
+    /* The movi is not explicitly generated here.  */
+    if (ots->val_type == TEMP_VAL_REG) {
+        s->reg_to_temp[ots->reg] = NULL;
     }
-    if (IS_DEAD_ARG(0)) {
+    ots->val_type = TEMP_VAL_CONST;
+    ots->val = val;
+    ots->mem_coherent = 0;
+    if (NEED_SYNC_ARG(0)) {
+        temp_sync(s, ots, s->reserved_regs, IS_DEAD_ARG(0));
+    } else if (IS_DEAD_ARG(0)) {
         temp_dead(s, ots);
     }
 }
@@ -2004,7 +2023,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
         ots->mem_coherent = 0;
         s->reg_to_temp[ots->reg] = ots;
         if (NEED_SYNC_ARG(0)) {
-            tcg_reg_sync(s, ots->reg, allocated_regs);
+            temp_sync(s, ots, allocated_regs, 0);
         }
     }
 }
@@ -2163,9 +2182,8 @@ static void tcg_reg_alloc_op(TCGContext *s,
             tcg_out_mov(s, ts->type, ts->reg, reg);
         }
         if (NEED_SYNC_ARG(i)) {
-            tcg_reg_sync(s, reg, allocated_regs);
-        }
-        if (IS_DEAD_ARG(i)) {
+            temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i));
+        } else if (IS_DEAD_ARG(i)) {
             temp_dead(s, ts);
         }
     }
@@ -2298,9 +2316,8 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
             ts->mem_coherent = 0;
             s->reg_to_temp[reg] = ts;
             if (NEED_SYNC_ARG(i)) {
-                tcg_reg_sync(s, reg, allocated_regs);
-            }
-            if (IS_DEAD_ARG(i)) {
+                temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i));
+            } else if (IS_DEAD_ARG(i)) {
                 temp_dead(s, ts);
             }
         }
diff --git a/tcg/tci/tcg-target.inc.c b/tcg/tci/tcg-target.inc.c
index fa74d52..3c47ea7 100644
--- a/tcg/tci/tcg-target.inc.c
+++ b/tcg/tci/tcg-target.inc.c
@@ -834,6 +834,12 @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
     old_code_ptr[1] = s->code_ptr - old_code_ptr;
 }
 
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+                               TCGReg base, intptr_t ofs)
+{
+    return false;
+}
+
 /* Test if a constant matches the constraint. */
 static int tcg_target_const_match(tcg_target_long val, TCGType type,
                                   const TCGArgConstraint *arg_ct)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [Qemu-devel] [PATCH v2 3/3] tcg: Rearrange register allocation
  2016-06-22  6:52 [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation Richard Henderson
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 1/3] tcg: Fix name for high-half register Richard Henderson
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 2/3] tcg: Optimize spills of constants Richard Henderson
@ 2016-06-22  6:52 ` Richard Henderson
  2016-06-22 19:00 ` [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc " Mark Cave-Ayland
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2016-06-22  6:52 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.cave-ayland, aurelien, thuth

With indirect_regs, and opcodes with enough inputs, on i686 we can
find ourselves in a situation in which there are no free registers,
and cannot load the indirect_base so that we can spill temps so that
we can free up registers.

When this happens, release the operands, sync all of the temps,
and restart operand collection from the beginning.

This does result in a few garbage instructions, but the situation
is rare; only happening once during a sparc64-linux boot to prompt.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c | 268 +++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 194 insertions(+), 74 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 44de991..d66048a 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1680,7 +1680,7 @@ static void temp_allocate_frame(TCGContext *s, int temp)
     s->current_frame_offset += sizeof(tcg_target_long);
 }
 
-static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet);
+static bool temp_load_may_fail(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet);
 
 /* Mark a temporary as free or dead.  If 'free_or_dead' is negative,
    mark it free; otherwise mark it dead.  */
@@ -1708,11 +1708,11 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts)
    registers needs to be allocated to store a constant.  If 'free_or_dead'
    is non-zero, subsequently release the temporary; if it is positive, the
    temp is dead; if it is negative, the temp is free.  */
-static void temp_sync(TCGContext *s, TCGTemp *ts,
-                      TCGRegSet allocated_regs, int free_or_dead)
+static bool temp_sync_may_fail(TCGContext *s, TCGTemp *ts,
+                               TCGRegSet allocated_regs, int free_or_dead)
 {
     if (ts->fixed_reg) {
-        return;
+        return true;
     }
     if (!ts->mem_coherent) {
         if (!ts->mem_allocated) {
@@ -1722,9 +1722,11 @@ static void temp_sync(TCGContext *s, TCGTemp *ts,
             if (ts->val_type == TEMP_VAL_REG) {
                 tcg_regset_set_reg(allocated_regs, ts->reg);
             }
-            temp_load(s, ts->mem_base,
-                      tcg_target_available_regs[TCG_TYPE_PTR],
-                      allocated_regs);
+            if (!temp_load_may_fail(s, ts->mem_base,
+                                    tcg_target_available_regs[TCG_TYPE_PTR],
+                                    allocated_regs)) {
+                return false;
+            }
         }
         switch (ts->val_type) {
         case TEMP_VAL_CONST:
@@ -1736,8 +1738,10 @@ static void temp_sync(TCGContext *s, TCGTemp *ts,
                                ts->mem_base->reg, ts->mem_offset)) {
                 break;
             }
-            temp_load(s, ts, tcg_target_available_regs[ts->type],
-                      allocated_regs);
+            if (!temp_load_may_fail(s, ts, tcg_target_available_regs[ts->type],
+                                    allocated_regs)) {
+                return false;
+            }
             /* fallthrough */
 
         case TEMP_VAL_REG:
@@ -1757,20 +1761,36 @@ static void temp_sync(TCGContext *s, TCGTemp *ts,
     if (free_or_dead) {
         temp_free_or_dead(s, ts, free_or_dead);
     }
+    return true;
+}
+
+static void temp_sync(TCGContext *s, TCGTemp *ts,
+                      TCGRegSet allocated_regs, int free_or_dead)
+{
+    bool ok = temp_sync_may_fail(s, ts, allocated_regs, free_or_dead);
+    tcg_debug_assert(ok);
 }
 
 /* free register 'reg' by spilling the corresponding temporary if necessary */
-static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
+static bool tcg_reg_free_may_fail(TCGContext *s, TCGReg reg,
+                                  TCGRegSet allocated_regs)
 {
     TCGTemp *ts = s->reg_to_temp[reg];
     if (ts != NULL) {
-        temp_sync(s, ts, allocated_regs, -1);
+        return temp_sync_may_fail(s, ts, allocated_regs, -1);
     }
+    return true;
+}
+
+static void tcg_reg_free(TCGContext *s, TCGReg reg, TCGRegSet allocated_regs)
+{
+    bool ok = tcg_reg_free_may_fail(s, reg, allocated_regs);
+    tcg_debug_assert(ok);
 }
 
 /* Allocate a register belonging to reg1 & ~reg2 */
-static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
-                            TCGRegSet allocated_regs, bool rev)
+static int tcg_reg_alloc_may_fail(TCGContext *s, TCGRegSet desired_regs,
+                                  TCGRegSet allocated_regs, bool rev)
 {
     int i, n = ARRAY_SIZE(tcg_target_reg_alloc_order);
     const int *order;
@@ -1781,49 +1801,98 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
     order = rev ? indirect_reg_alloc_order : tcg_target_reg_alloc_order;
 
     /* first try free registers */
-    for(i = 0; i < n; i++) {
+    for (i = 0; i < n; i++) {
         reg = order[i];
-        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL)
+        if (tcg_regset_test_reg(reg_ct, reg) && s->reg_to_temp[reg] == NULL) {
             return reg;
+        }
     }
 
     /* XXX: do better spill choice */
-    for(i = 0; i < n; i++) {
+    for (i = 0; i < n; i++) {
         reg = order[i];
-        if (tcg_regset_test_reg(reg_ct, reg)) {
-            tcg_reg_free(s, reg, allocated_regs);
+        if (tcg_regset_test_reg(reg_ct, reg)
+            && tcg_reg_free_may_fail(s, reg, allocated_regs)) {
             return reg;
         }
     }
 
-    tcg_abort();
+    return -1;
+}
+
+static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet desired_regs,
+                            TCGRegSet allocated_regs, bool rev)
+{
+    int r = tcg_reg_alloc_may_fail(s, desired_regs, allocated_regs, rev);
+    tcg_debug_assert(r >= 0);
+    return r;
 }
 
 /* Make sure the temporary is in a register.  If needed, allocate the register
    from DESIRED while avoiding ALLOCATED.  */
-static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
-                      TCGRegSet allocated_regs)
+static bool temp_load_may_fail(TCGContext *s, TCGTemp *ts,
+                               TCGRegSet desired_regs,
+                               TCGRegSet allocated_regs)
 {
-    TCGReg reg;
+    int reg, base_reg;
+    TCGTemp *base;
 
     switch (ts->val_type) {
     case TEMP_VAL_REG:
-        return;
+        return true;
+
     case TEMP_VAL_CONST:
-        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
+        reg = tcg_reg_alloc_may_fail(s, desired_regs, allocated_regs,
+                                     ts->indirect_base);
+        if (reg < 0) {
+            return false;
+        }
         tcg_out_movi(s, ts->type, reg, ts->val);
         break;
+
     case TEMP_VAL_MEM:
-        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, ts->indirect_base);
+        reg = tcg_reg_alloc_may_fail(s, desired_regs, allocated_regs,
+                                     ts->indirect_base);
+        if (reg < 0) {
+            return false;
+        }
+
+        /* If this register is itself an indirect_base, we may have
+           allocated it during recursion while syncing an indirect_reg.  */
+        if (ts->val_type == TEMP_VAL_REG) {
+            tcg_debug_assert(ts->indirect_base);
+            return true;
+        }
+
+        base = ts->mem_base;
+        base_reg = base->reg;
         if (ts->indirect_reg) {
             tcg_regset_set_reg(allocated_regs, reg);
-            temp_load(s, ts->mem_base,
-                      tcg_target_available_regs[TCG_TYPE_PTR],
-                      allocated_regs);
+            if (temp_load_may_fail(s, base,
+                                   tcg_target_available_regs[TCG_TYPE_PTR],
+                                   allocated_regs)) {
+                base_reg = base->reg;
+            } else {
+                /* There was only one available register.  Since this is a
+                   load, we can get away with re-using the one that we
+                   allocated for TS.  But recurse again just to be sure.  */
+                tcg_regset_reset_reg(allocated_regs, reg);
+                if (!temp_load_may_fail(s, base,
+                                        tcg_target_available_regs[TCG_TYPE_PTR],
+                                        allocated_regs)) {
+                    return false;
+                }
+                tcg_debug_assert(base->reg == reg);
+                base_reg = reg;
+                /* And because we're re-using the register,
+                   make sure to properly mark it clobbered.  */
+                temp_free_or_dead(s, base, -1);
+            }
         }
-        tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
+        tcg_out_ld(s, ts->type, reg, base_reg, ts->mem_offset);
         ts->mem_coherent = 1;
         break;
+
     case TEMP_VAL_DEAD:
     default:
         tcg_abort();
@@ -1831,6 +1900,14 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
     ts->reg = reg;
     ts->val_type = TEMP_VAL_REG;
     s->reg_to_temp[reg] = ts;
+    return true;
+}
+
+static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
+                      TCGRegSet allocated_regs)
+{
+    bool ok = temp_load_may_fail(s, ts, desired_regs, allocated_regs);
+    tcg_debug_assert(ok);
 }
 
 /* save a temporary to memory. 'allocated_regs' is used in case a
@@ -1865,21 +1942,24 @@ static void save_globals(TCGContext *s, TCGRegSet allocated_regs)
 /* sync globals to their canonical location and assume they can be
    read by the following code. 'allocated_regs' is used in case a
    temporary registers needs to be allocated to store a constant. */
-static void sync_globals(TCGContext *s, TCGRegSet allocated_regs)
+static void sync_globals(TCGContext *s, TCGRegSet allocated_regs,
+                         bool forced)
 {
     int i;
 
     for (i = 0; i < s->nb_globals; i++) {
         TCGTemp *ts = &s->temps[i];
+        if (!forced) {
 #ifdef USE_LIVENESS_ANALYSIS
-        /* ??? Liveness does not yet incorporate indirect bases.  */
-        if (!ts->indirect_base) {
-            tcg_debug_assert(ts->val_type != TEMP_VAL_REG
-                             || ts->fixed_reg
-                             || ts->mem_coherent);
-            continue;
-        }
+            /* ??? Liveness does not yet incorporate indirect bases.  */
+            if (!ts->indirect_base) {
+                tcg_debug_assert(ts->val_type != TEMP_VAL_REG
+                                 || ts->fixed_reg
+                                 || ts->mem_coherent);
+                continue;
+            }
 #endif
+        }
         temp_sync(s, ts, allocated_regs, 0);
     }
 }
@@ -2028,12 +2108,12 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
     }
 }
 
-static void tcg_reg_alloc_op(TCGContext *s, 
+static void tcg_reg_alloc_op(TCGContext *s,
                              const TCGOpDef *def, TCGOpcode opc,
                              const TCGArg *args, uint16_t dead_args,
                              uint8_t sync_args)
 {
-    TCGRegSet allocated_regs;
+    TCGRegSet in_alloc_regs, out_alloc_regs;
     int i, k, nb_iargs, nb_oargs;
     TCGReg reg;
     TCGArg arg;
@@ -2041,18 +2121,49 @@ static void tcg_reg_alloc_op(TCGContext *s,
     TCGTemp *ts;
     TCGArg new_args[TCG_MAX_OP_ARGS];
     int const_args[TCG_MAX_OP_ARGS];
+    bool may_restart;
+    int reg_tst;
 
     nb_oargs = def->nb_oargs;
     nb_iargs = def->nb_iargs;
 
-    /* copy constants */
-    memcpy(new_args + nb_oargs + nb_iargs, 
-           args + nb_oargs + nb_iargs, 
+    /* Copy constants.  */
+    memcpy(new_args + nb_oargs + nb_iargs,
+           args + nb_oargs + nb_iargs,
            sizeof(TCGArg) * def->nb_cargs);
 
-    /* satisfy input constraints */ 
-    tcg_regset_set(allocated_regs, s->reserved_regs);
-    for(k = 0; k < nb_iargs; k++) {
+    /* Sync globals if the op has side effects and might
+       trigger an exception.  */
+    if (def->flags & TCG_OPF_SIDE_EFFECTS) {
+        may_restart = false;
+        goto do_sync;
+    }
+
+    may_restart = true;
+    goto start;
+
+ restart:
+    /* Register allocation failed.  If the guest uses indirect
+       registers, we had all available regs allocated to temps
+       that required a base register to sync.  Drop all args,
+       sync all globals, and restart.  Notice if we try to do
+       this more than once.  If that happens, we can't proceed.  */
+    /* ??? It would be nice if we could drop all of the insns we
+       have emitted so far, but then we'd be out-of-sync with
+       the register state in temps[].  */
+    if (!may_restart) {
+        tcg_abort();
+    }
+
+ do_sync:
+    sync_globals(s, s->reserved_regs, may_restart);
+    may_restart = false;
+
+ start:
+    tcg_regset_set(in_alloc_regs, s->reserved_regs);
+
+    /* Satisfy input constraints.  */
+    for (k = 0; k < nb_iargs; k++) {
         i = def->sorted_args[nb_oargs + k];
         arg = args[i];
         arg_ct = &def->args_ct[i];
@@ -2066,7 +2177,9 @@ static void tcg_reg_alloc_op(TCGContext *s,
             goto iarg_end;
         }
 
-        temp_load(s, ts, arg_ct->u.regs, allocated_regs);
+        if (!temp_load_may_fail(s, ts, arg_ct->u.regs, in_alloc_regs)) {
+            goto restart;
+        }
 
         if (arg_ct->ct & TCG_CT_IALIAS) {
             if (ts->fixed_reg) {
@@ -2098,18 +2211,22 @@ static void tcg_reg_alloc_op(TCGContext *s,
             /* nothing to do : the constraint is satisfied */
         } else {
         allocate_in_reg:
-            /* allocate a new register matching the constraint 
+            /* allocate a new register matching the constraint
                and move the temporary register into it */
-            reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs,
-                                ts->indirect_base);
+            reg_tst = tcg_reg_alloc_may_fail(s, arg_ct->u.regs, in_alloc_regs,
+                                             ts->indirect_base);
+            if (reg_tst < 0) {
+                goto restart;
+            }
+            reg = reg_tst;
             tcg_out_mov(s, ts->type, reg, ts->reg);
         }
         new_args[i] = reg;
         const_args[i] = 0;
-        tcg_regset_set_reg(allocated_regs, reg);
+        tcg_regset_set_reg(in_alloc_regs, reg);
     iarg_end: ;
     }
-    
+
     /* mark dead temporaries and free the associated registers */
     for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
         if (IS_DEAD_ARG(i)) {
@@ -2117,26 +2234,22 @@ static void tcg_reg_alloc_op(TCGContext *s,
         }
     }
 
+    tcg_regset_set(out_alloc_regs, s->reserved_regs);
     if (def->flags & TCG_OPF_BB_END) {
-        tcg_reg_alloc_bb_end(s, allocated_regs);
+        tcg_reg_alloc_bb_end(s, in_alloc_regs);
     } else {
         if (def->flags & TCG_OPF_CALL_CLOBBER) {
-            /* XXX: permit generic clobber register list ? */ 
+            /* XXX: permit generic clobber register list ? */
             for (i = 0; i < TCG_TARGET_NB_REGS; i++) {
-                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, i)) {
-                    tcg_reg_free(s, i, allocated_regs);
+                if (tcg_regset_test_reg(tcg_target_call_clobber_regs, i)
+                    && !tcg_reg_free_may_fail(s, i, in_alloc_regs)) {
+                    goto restart;
                 }
             }
         }
-        if (def->flags & TCG_OPF_SIDE_EFFECTS) {
-            /* sync globals if the op has side effects and might trigger
-               an exception. */
-            sync_globals(s, allocated_regs);
-        }
-        
-        /* satisfy the output constraints */
-        tcg_regset_set(allocated_regs, s->reserved_regs);
-        for(k = 0; k < nb_oargs; k++) {
+
+        /* Satisfy the output constraints.  */
+        for (k = 0; k < nb_oargs; k++) {
             i = def->sorted_args[k];
             arg = args[i];
             arg_ct = &def->args_ct[i];
@@ -2150,11 +2263,17 @@ static void tcg_reg_alloc_op(TCGContext *s,
                     tcg_regset_test_reg(arg_ct->u.regs, reg)) {
                     goto oarg_end;
                 }
-                reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs,
-                                    ts->indirect_base);
+                reg_tst = tcg_reg_alloc_may_fail(s, arg_ct->u.regs,
+                                                 out_alloc_regs,
+                                                 ts->indirect_base);
+                if (reg_tst < 0) {
+                    goto restart;
+                }
+                reg = reg_tst;
             }
-            tcg_regset_set_reg(allocated_regs, reg);
-            /* if a fixed register is used, then a move will be done afterwards */
+            tcg_regset_set_reg(out_alloc_regs, reg);
+            /* If a fixed register is used, then a move will be
+               done afterwards.  */
             if (!ts->fixed_reg) {
                 if (ts->val_type == TEMP_VAL_REG) {
                     s->reg_to_temp[ts->reg] = NULL;
@@ -2171,21 +2290,22 @@ static void tcg_reg_alloc_op(TCGContext *s,
         }
     }
 
-    /* emit instruction */
+    /* Emit instruction.  */
     tcg_out_op(s, opc, new_args, const_args);
-    
-    /* move the outputs in the correct register if needed */
-    for(i = 0; i < nb_oargs; i++) {
+
+    /* Move the outputs in the correct register if needed.  */
+    for (i = 0; i < nb_oargs; i++) {
         ts = &s->temps[args[i]];
         reg = new_args[i];
         if (ts->fixed_reg && ts->reg != reg) {
             tcg_out_mov(s, ts->type, ts->reg, reg);
         }
         if (NEED_SYNC_ARG(i)) {
-            temp_sync(s, ts, allocated_regs, IS_DEAD_ARG(i));
+            temp_sync(s, ts, out_alloc_regs, IS_DEAD_ARG(i));
         } else if (IS_DEAD_ARG(i)) {
             temp_dead(s, ts);
         }
+        tcg_regset_set_reg(out_alloc_regs, reg);
     }
 }
 
@@ -2289,7 +2409,7 @@ static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
     if (flags & TCG_CALL_NO_READ_GLOBALS) {
         /* Nothing to do */
     } else if (flags & TCG_CALL_NO_WRITE_GLOBALS) {
-        sync_globals(s, allocated_regs);
+        sync_globals(s, allocated_regs, false);
     } else {
         save_globals(s, allocated_regs);
     }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation
  2016-06-22  6:52 [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation Richard Henderson
                   ` (2 preceding siblings ...)
  2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 3/3] tcg: Rearrange register allocation Richard Henderson
@ 2016-06-22 19:00 ` Mark Cave-Ayland
  3 siblings, 0 replies; 5+ messages in thread
From: Mark Cave-Ayland @ 2016-06-22 19:00 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: thuth, aurelien

On 22/06/16 07:52, Richard Henderson wrote:

> Attempting to fix the problem reported by Mark re i686 vs sparc64.
>
> Unsurprisingly, the problems tend to revolve around the 6 operand
> opcodes like sub2 or qemu_st64, where we use all, or all but one
> register.
>
>
> r~
>
>
> Richard Henderson (3):
>   tcg: Fix name for high-half register
>   tcg: Optimize spills of constants
>   tcg: Rearrange register allocation
>
>  tcg/aarch64/tcg-target.inc.c |  10 ++
>  tcg/arm/tcg-target.inc.c     |   6 +
>  tcg/i386/tcg-target.inc.c    |  21 ++-
>  tcg/ia64/tcg-target.inc.c    |  10 ++
>  tcg/mips/tcg-target.inc.c    |  10 ++
>  tcg/ppc/tcg-target.inc.c     |   6 +
>  tcg/s390/tcg-target.inc.c    |   6 +
>  tcg/sparc/tcg-target.inc.c   |  10 ++
>  tcg/tcg.c                    | 409 +++++++++++++++++++++++++++++--------------
>  tcg/tci/tcg-target.inc.c     |   6 +
>  10 files changed, 351 insertions(+), 143 deletions(-)

Hi Richard,

This version is much improved, although I was still able to detect a 
regression booting my OpenBSD 5.5/sparc64 (install55.iso) test image in 
an i386 VM:


./qemu-system-sparc64 -cdrom install55.iso -boot d -nographic
OpenBIOS for Sparc64
Configuration device id QEMU version 1 machine id 0
kernel cmdline
CPUs: 1 x SUNW,UltraSPARC-IIi
UUID: 00000000-0000-0000-0000-000000000000
Welcome to OpenBIOS v1.1 built on Apr 18 2016 08:20
   Type 'help' for detailed information
Trying cdrom:f...
Not a bootable ELF image
Not a bootable a.out image

Loading FCode image...
Loaded 4829 bytes
entry point is 0x4000
OpenBSD IEEE 1275 Bootblock 1.3
..
Jumping to entry point 0000000000100000 for type 0000000000000001...
switching to new context: entry point 0x100000 stack 0x00000000ffe84a09
 >> OpenBSD BOOT 1.6
Trying bsd...
open /pci@1fe,0/pci-ata@5/ide1@8200/cdrom@0:f/etc/random.seed: No such 
file or directory
Booting /pci@1fe,0/pci-ata@5/ide1@8200/cdrom@0:f/bsd
3901336@0x1000000+6248@0x13b8798+3261984@0x1800000+932320@0x1b1c620
symbols @ 0xffc5a300 119 start=0x1000000

Unexpected client interface exception: -1
console is /pci@1fe,0/ebus@3/su
Copyright (c) 1982, 1986, 1989, 1991, 1993
         The Regents of the University of California.  All rights reserved.
Copyright (c) 1995-2014 OpenBSD. All rights reserved. 
http://www.OpenBSD.org

OpenBSD 5.5 (RAMDISK) #153: Tue Mar  4 15:12:10 MST 2014
     deraadt@sparc64.openbsd.org:/usr/src/sys/arch/sparc64/compile/RAMDISK
real mem = 134217728 (128MB)
avail mem = 122011648 (116MB)
mainbus0 at root: OpenBiosTeam,OpenBIOS
cpu0 at mainbus0: SUNW,UltraSPARC-IIi (rev 9.1) @ 100 MHz
cpu0: physical 256K instruction (64 b/l), 16K data (32 b/l), 256K 
external (64 b/l)
psycho0 at mainbus0: SUNW,sabre, impl 0, version 0, ign 7c0
psycho0: bus range 0-2, PCI bus 0
psycho0: dvma map c0000000-dfffffff
pci0 at psycho0
ppb0 at pci0 dev 1 function 0 "Sun Simba" rev 0x11
pci1 at ppb0 bus 1
ppb1 at pci0 dev 1 function 1 "Sun Simba" rev 0x11
pci2 at ppb1 bus 2
unknown vendor 0x1234 product 0x1111 (class display subclass VGA, rev 
0x02) at pci0 dev 2 function 0 not configured
ebus0 at pci0 dev 3 function 0 "Sun PCIO EBus2" rev 0x01
clock1 at ebus0 addr 2000-3fff: mk48t59
"fdthree" at ebus0 addr 0-ffffffff not configured
com0 at ebus0 addr 3f8-3ff ivec 0x2b: ns16550a, 16 byte fifo
com0: console
"kb_ps2" at ebus0 addr 60-67 not configured
"Realtek 8029" rev 0x00 at pci0 dev 4 function 0 not configured
pciide0 at pci0 dev 5 function 0 "CMD Technology PCI0646" rev 0x07: DMA, 
channel 0 configured to native-PCI, channel 1 configured to native-PCI
pciide0: using ivec 0x7d4 for native-PCI interrupt
pciide0: channel 0 disabled (no drives)
atapiscsi0 at pciide0 channel 1 drive 0
scsibus0 at atapiscsi0: 2 targets
cd0 at scsibus0 targ 0 lun 0: <QEMU, QEMU DVD-ROM, 2.5+> ATAPI 5/cdrom 
removable
cd0(pciide0:1:0): using PIO mode 4, Ultra-DMA mode 2
panic: kernel data fault: pc=1011d9c addr=0
syncing disks... panic: kernel data fault: pc=1011d9c addr=0
Frame pointer is at 0x1c088d1
Call traceback:
1298a34(1b08938, 5, 0, 0, 1c092d8, 0, 1c08991) fp = 1c08991
1107ef8(104, 1c093a8, 1b08000, 1c093a8, 0, 82d, 1c08a51) fp = 1c08a51
12a0b80(13a7b48, 1011d9c, 1b75000, 3, 104, 7fd8, 1c08b21) fp = 1c08b21
1010790(0, 30, 1011d9c, 0, 0, 82d, 1c08be1) fp = 1c08be1
1107bbc(1b08938, 5, 0, 0, 1c09718, 0, 1c08dc1) fp = 1c08dc1
11242c8(11, 5, 1b08000, 0, 13, 0, 1c08e91) fp = 1c08e91
12989b4(1b08938, 5, 0, 0, 1c09898, 0, 1c08f51) fp = 1c08f51
1107ef8(100, 1c09968, 1b08000, 1c09968, ffd0cc58, 1801010, 1c09011) fp = 
1c09011
12a0b80(13a7b48, 1011d9c, 1b75000, 3, 100, 0, 1c090e1) fp = 1c090e1
1010790(0, 30, 1011d9c, 0, 0, 82d, 1c091a1) fp = 1c091a1
1137080(0, 400026ac000, fffffffffffffff8, 0, 400001df100, 1b6b478, 
1c09381) fp = 1c09381
1137140(1b09000, 400001df100, 0, 18e0, 30, 400001df150, 1c09441) fp = 
1c09441
113af10(400001dd800, 400001df100, 400001dd800, 0, 502, 0, 1c09501) fp = 
1c09501
113af4c(0, 0, 1101574, 502, 0, 28, 1c095c1) fp = 1c095c1
10ebc3c(1b098b0, 400002c6e48, 0, ffffffffffffe000, 1, 1, 1c09681) fp = 
1c09681
1012310(0, 10eb760, 18, ffd0cc58, ffd0cc58, 1801010, 1c09751) fp = 1c09751
1012a4(100000, 1cf8, 1000000, ffe84e38, 18, 10b9e8, ffe84549) fp = ffe84549

dump to dev 5,1 not possible
rebooting

BOOTpanic: OF_boot failed
Frame pointer is at 0x1c08661
Call traceback:
1298a34(1b08938, 5, 0, 0, 1c09068, 0, 1c08721) fp = 1c08721
1107ef8(104, 1c09138, 1b08000, 1c09138, 1000000, ffe84e38, 1c087e1) fp = 
1c087e1
129ab94(13a6fe8, 1b69761, 1b75000, f, 104, 0, 1c088b1) fp = 1c088b1
1298b84(1b69760, 6, 1b08000, 0, 1c092d8, 0, 1c08991) fp = 1c08991
1107ef8(104, 1c093a8, 1b08000, 1c093a8, 0, 82d, 1c08a51) fp = 1c08a51
12a0b80(13a7b48, 1011d9c, 1b75000, 3, 104, 7fd8, 1c08b21) fp = 1c08b21
1010790(0, 30, 1011d9c, 0, 0, 82d, 1c08be1) fp = 1c08be1
1107bbc(1b08938, 5, 0, 0, 1c09718, 0, 1c08dc1) fp = 1c08dc1
11242c8(11, 5, 1b08000, 0, 13, 0, 1c08e91) fp = 1c08e91
12989b4(1b08938, 5, 0, 0, 1c09898, 0, 1c08f51) fp = 1c08f51
1107ef8(100, 1c09968, 1b08000, 1c09968, ffd0cc58, 1801010, 1c09011) fp = 
1c09011
12a0b80(13a7b48, 1011d9c, 1b75000, 3, 100, 0, 1c090e1) fp = 1c090e1
1010790(0, 30, 1011d9c, 0, 0, 82d, 1c091a1) fp = 1c091a1
1137080(0, 400026ac000, fffffffffffffff8, 0, 400001df100, 1b6b478, 
1c09381) fp = 1c09381
1137140(1b09000, 400001df100, 0, 18e0, 30, 400001df150, 1c09441) fp = 
1c09441
113af10(400001dd800, 400001df100, 400001dd800, 0, 502, 0, 1c09501) fp = 
1c09501
113af4c(0, 0, 1101574, 502, 0, 28, 1c095c1) fp = 1c095c1
10ebc3c(1b098b0, 400002c6e48, 0, ffffffffffffe000, 1, 1, 1c09681) fp = 
1c09681
1012310(0, 10eb760, 18, ffd0cc58, ffd0cc58, 1801010, 1c09751) fp = 1c09751
1012a4(100000, 1cf8, 1000000, ffe84e38, 18, 10b9e8, ffe84549) fp = ffe84549

dump to dev 5,1 not possible
rebooting


I applied this patchset to my current x86_64 build tree and verified 
that everything still works there, so the error appears to be limited to 
an i386 host.


ATB,

Mark.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-06-22 19:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22  6:52 [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc register allocation Richard Henderson
2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 1/3] tcg: Fix name for high-half register Richard Henderson
2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 2/3] tcg: Optimize spills of constants Richard Henderson
2016-06-22  6:52 ` [Qemu-devel] [PATCH v2 3/3] tcg: Rearrange register allocation Richard Henderson
2016-06-22 19:00 ` [Qemu-devel] [PATCH v2 0/3] Second try at fixing sparc " Mark Cave-Ayland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.