Hi,

(old patch merged as commit b68e60e6f0d2865e961a800fb8db96a7fc6494c4)

On 31/5/16 02:41, David Gibson wrote:
From: Benjamin Herrenschmidt <b...@kernel.crashing.org>

Otherwise tight loops at smt_low for example, which OPAL does,
eat so much CPU that we can't boot a kernel anymore. With that,
I can boot 8 CPUs just fine with powernv.

Signed-off-by: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Reviewed-by: David Gibson <da...@gibson.dropbear.id.au>
Signed-off-by: David Gibson <da...@gibson.dropbear.id.au>
---
  target-ppc/translate.c | 21 ++++++++++++++++++---
  1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 51f6eb1..fe10bf8 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -1392,6 +1392,19 @@ GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
  /* nor & nor. */
  GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
+#if defined(TARGET_PPC64)
+static void gen_pause(DisasContext *ctx)
+{
+    TCGv_i32 t0 = tcg_const_i32(0);
+    tcg_gen_st_i32(t0, cpu_env,
+                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));

This sets CPUState::halted = 0, as unhalted state (a.k.a. "running"),
is that expected? I'd expect "Pause" to halt the vCPU to avoid spinning
(as mentioned below).

+    tcg_temp_free_i32(t0);
+
+    /* Stop translation, this gives other CPUs a chance to run */
+    gen_exception_err(ctx, EXCP_HLT, 1);
+}
+#endif /* defined(TARGET_PPC64) */
+
  /* or & or. */
  static void gen_or(DisasContext *ctx)
  {
@@ -1447,7 +1460,7 @@ static void gen_or(DisasContext *ctx)
              }
              break;
          case 7:
-            if (ctx->hv) {
+            if (ctx->hv && !ctx->pr) {
                  /* Set process priority to very high */
                  prio = 7;
              }
@@ -1464,6 +1477,10 @@ static void gen_or(DisasContext *ctx)
              tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
              gen_store_spr(SPR_PPR, t0);
              tcg_temp_free(t0);
+            /* Pause us out of TCG otherwise spin loops with smt_low
+             * eat too much CPU and the kernel hangs
+             */
+            gen_pause(ctx);
          }
  #endif
      }
@@ -1489,8 +1506,6 @@ static void gen_ori(DisasContext *ctx)
      target_ulong uimm = UIMM(ctx->opcode);
if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
-        /* NOP */
-        /* XXX: should handle special NOPs for POWER series */
          return;
      }
      tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
Note there is a similar code in gen_wait() doing the same (but correctlyIMO):

 3366  /*
3367 * wait without WC field or with WC=0 waits for an exception / interrupt
 3368   * to occur.
 3369   */
 3370  if (wc == 0) {
 3371      TCGv_i32 t0 = tcg_constant_i32(1);
 3372      tcg_gen_st_i32(t0, tcg_env,
3373 -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
 3374      /* Stop translation, as the CPU is supposed to sleep from now */
 3375      gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
 3376  }


Reply via email to