[Qemu-devel] [PATCH v2] target/ppc: add support for hypervisor doorbells on book3s CPUs

Cédric Le Goater posted 1 patch 6 years, 3 months ago
Failed in applying to current master (apply log)
target/ppc/cpu.h            |  8 +++++--
target/ppc/excp_helper.c    | 52 +++++++++++++++++++++++++++++++++++++++++++++
target/ppc/helper.h         |  2 ++
target/ppc/translate.c      | 25 ++++++++++++++++++++--
target/ppc/translate_init.c |  2 +-
5 files changed, 84 insertions(+), 5 deletions(-)
[Qemu-devel] [PATCH v2] target/ppc: add support for hypervisor doorbells on book3s CPUs
Posted by Cédric Le Goater 6 years, 3 months ago
The hypervisor doorbells are used by skiboot and Linux on POWER9
processors to wake up secondaries.

This adds processor control support to the Server architecture by
reusing the Embedded support. They are very similar, only the bits
definition of the CPU identifier differ.

Still to be done is message broadcast to all threads of the same
processor.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
---

 Changes since v2:

 - introduced specific msgclr/snd helpers for book3s 

 target/ppc/cpu.h            |  8 +++++--
 target/ppc/excp_helper.c    | 52 +++++++++++++++++++++++++++++++++++++++++++++
 target/ppc/helper.h         |  2 ++
 target/ppc/translate.c      | 25 ++++++++++++++++++++--
 target/ppc/translate_init.c |  2 +-
 5 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index b8f4dfc1084a..603a38cae83f 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -930,7 +930,7 @@ enum {
 #define BOOKE206_MAX_TLBN      4
 
 /*****************************************************************************/
-/* Embedded.Processor Control */
+/* Server and Embedded Processor Control */
 
 #define DBELL_TYPE_SHIFT               27
 #define DBELL_TYPE_MASK                (0x1f << DBELL_TYPE_SHIFT)
@@ -940,11 +940,15 @@ enum {
 #define DBELL_TYPE_G_DBELL_CRIT        (0x03 << DBELL_TYPE_SHIFT)
 #define DBELL_TYPE_G_DBELL_MC          (0x04 << DBELL_TYPE_SHIFT)
 
-#define DBELL_BRDCAST                  (1 << 26)
+#define DBELL_TYPE_DBELL_SERVER        (0x05 << DBELL_TYPE_SHIFT)
+
+#define DBELL_BRDCAST                  PPC_BIT(37)
 #define DBELL_LPIDTAG_SHIFT            14
 #define DBELL_LPIDTAG_MASK             (0xfff << DBELL_LPIDTAG_SHIFT)
 #define DBELL_PIRTAG_MASK              0x3fff
 
+#define DBELL_PROCIDTAG_MASK           PPC_BITMASK(44, 63)
+
 /*****************************************************************************/
 /* Segment page size information, used by recent hash MMUs
  * The format of this structure mirrors kvm_ppc_smmu_info
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 4e548a448747..c092fbead036 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -417,6 +417,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
     case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
     case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
     case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
+    case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
     case POWERPC_EXCP_HV_EMU:
         srr0 = SPR_HSRR0;
         srr1 = SPR_HSRR1;
@@ -846,6 +847,11 @@ static void ppc_hw_interrupt(CPUPPCState *env)
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
             return;
         }
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
+            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
+            return;
+        }
         if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
             powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
@@ -1145,4 +1151,50 @@ void helper_msgsnd(target_ulong rb)
     }
     qemu_mutex_unlock_iothread();
 }
+
+/* Server Processor Control */
+static int book3s_dbell2irq(target_ulong rb)
+{
+    int msg = rb & DBELL_TYPE_MASK;
+
+    /* A Directed Hypervisor Doorbell message is sent only if the
+     * message type is 5. All other types are reserved and the
+     * instruction is a no-op */
+    return msg == DBELL_TYPE_DBELL_SERVER ? PPC_INTERRUPT_HDOORBELL : -1;
+}
+
+void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
+{
+    int irq = book3s_dbell2irq(rb);
+
+    if (irq < 0) {
+        return;
+    }
+
+    env->pending_interrupts &= ~(1 << irq);
+}
+
+void helper_book3s_msgsnd(target_ulong rb)
+{
+    int irq = book3s_dbell2irq(rb);
+    int pir = rb & DBELL_PROCIDTAG_MASK;
+    CPUState *cs;
+
+    if (irq < 0) {
+        return;
+    }
+
+    qemu_mutex_lock_iothread();
+    CPU_FOREACH(cs) {
+        PowerPCCPU *cpu = POWERPC_CPU(cs);
+        CPUPPCState *cenv = &cpu->env;
+
+        /* TODO: broadcast message to all threads of the same  processor */
+        if (cenv->spr_cb[SPR_PIR].default_value == pir) {
+            cenv->pending_interrupts |= 1 << irq;
+            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+        }
+    }
+    qemu_mutex_unlock_iothread();
+}
 #endif
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index bb6a94a8b390..5b739179b8b5 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -679,6 +679,8 @@ DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl)
 DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_1(msgsnd, void, tl)
 DEF_HELPER_2(msgclr, void, env, tl)
+DEF_HELPER_1(book3s_msgsnd, void, tl)
+DEF_HELPER_2(book3s_msgclr, void, env, tl)
 #endif
 
 DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 396f422cf407..4325aa90a6fa 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6175,7 +6175,12 @@ static void gen_msgclr(DisasContext *ctx)
     GEN_PRIV;
 #else
     CHK_HV;
-    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+    /* 64-bit server processors compliant with arch 2.x */
+    if (ctx->insns_flags & PPC_SEGMENT_64B) {
+        gen_helper_book3s_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+    } else {
+        gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+    }
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -6185,10 +6190,24 @@ static void gen_msgsnd(DisasContext *ctx)
     GEN_PRIV;
 #else
     CHK_HV;
-    gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
+    /* 64-bit server processors compliant with arch 2.x */
+    if (ctx->insns_flags & PPC_SEGMENT_64B) {
+        gen_helper_book3s_msgsnd(cpu_gpr[rB(ctx->opcode)]);
+    } else {
+        gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
+    }
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
+static void gen_msgsync(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+    GEN_PRIV;
+#else
+    CHK_HV;
+#endif /* defined(CONFIG_USER_ONLY) */
+    /* interpreted as no-op */
+}
 
 #if defined(TARGET_PPC64)
 static void gen_maddld(DisasContext *ctx)
@@ -6669,6 +6688,8 @@ GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
                PPC_NONE, PPC2_PRCNTL),
 GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
                PPC_NONE, PPC2_PRCNTL),
+GEN_HANDLER2_E(msgsync, "msgsync", 0x1F, 0x16, 0x1B, 0x00000000,
+               PPC_NONE, PPC2_PRCNTL),
 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
 GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index ab70b3a25c1d..87a23f0f6265 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -8866,7 +8866,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
                         PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
                         PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
                         PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
-                        PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300;
+                        PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300 | PPC2_PRCNTL;
     pcc->msr_mask = (1ull << MSR_SF) |
                     (1ull << MSR_TM) |
                     (1ull << MSR_VR) |
-- 
2.13.6


Re: [Qemu-devel] [PATCH v2] target/ppc: add support for hypervisor doorbells on book3s CPUs
Posted by David Gibson 6 years, 3 months ago
On Thu, Jan 18, 2018 at 03:54:03PM +0100, Cédric Le Goater wrote:
> The hypervisor doorbells are used by skiboot and Linux on POWER9
> processors to wake up secondaries.
> 
> This adds processor control support to the Server architecture by
> reusing the Embedded support. They are very similar, only the bits
> definition of the CPU identifier differ.
> 
> Still to be done is message broadcast to all threads of the same
> processor.
> 
> Signed-off-by: Cédric Le Goater <clg@kaod.org>

Applied to ppc-for-2.12, thanks.

> ---
> 
>  Changes since v2:
> 
>  - introduced specific msgclr/snd helpers for book3s 
> 
>  target/ppc/cpu.h            |  8 +++++--
>  target/ppc/excp_helper.c    | 52 +++++++++++++++++++++++++++++++++++++++++++++
>  target/ppc/helper.h         |  2 ++
>  target/ppc/translate.c      | 25 ++++++++++++++++++++--
>  target/ppc/translate_init.c |  2 +-
>  5 files changed, 84 insertions(+), 5 deletions(-)
> 
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index b8f4dfc1084a..603a38cae83f 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -930,7 +930,7 @@ enum {
>  #define BOOKE206_MAX_TLBN      4
>  
>  /*****************************************************************************/
> -/* Embedded.Processor Control */
> +/* Server and Embedded Processor Control */
>  
>  #define DBELL_TYPE_SHIFT               27
>  #define DBELL_TYPE_MASK                (0x1f << DBELL_TYPE_SHIFT)
> @@ -940,11 +940,15 @@ enum {
>  #define DBELL_TYPE_G_DBELL_CRIT        (0x03 << DBELL_TYPE_SHIFT)
>  #define DBELL_TYPE_G_DBELL_MC          (0x04 << DBELL_TYPE_SHIFT)
>  
> -#define DBELL_BRDCAST                  (1 << 26)
> +#define DBELL_TYPE_DBELL_SERVER        (0x05 << DBELL_TYPE_SHIFT)
> +
> +#define DBELL_BRDCAST                  PPC_BIT(37)
>  #define DBELL_LPIDTAG_SHIFT            14
>  #define DBELL_LPIDTAG_MASK             (0xfff << DBELL_LPIDTAG_SHIFT)
>  #define DBELL_PIRTAG_MASK              0x3fff
>  
> +#define DBELL_PROCIDTAG_MASK           PPC_BITMASK(44, 63)
> +
>  /*****************************************************************************/
>  /* Segment page size information, used by recent hash MMUs
>   * The format of this structure mirrors kvm_ppc_smmu_info
> diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
> index 4e548a448747..c092fbead036 100644
> --- a/target/ppc/excp_helper.c
> +++ b/target/ppc/excp_helper.c
> @@ -417,6 +417,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
>      case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
>      case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
>      case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
> +    case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
>      case POWERPC_EXCP_HV_EMU:
>          srr0 = SPR_HSRR0;
>          srr1 = SPR_HSRR1;
> @@ -846,6 +847,11 @@ static void ppc_hw_interrupt(CPUPPCState *env)
>              powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
>              return;
>          }
> +        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
> +            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
> +            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
> +            return;
> +        }
>          if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
>              env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
>              powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
> @@ -1145,4 +1151,50 @@ void helper_msgsnd(target_ulong rb)
>      }
>      qemu_mutex_unlock_iothread();
>  }
> +
> +/* Server Processor Control */
> +static int book3s_dbell2irq(target_ulong rb)
> +{
> +    int msg = rb & DBELL_TYPE_MASK;
> +
> +    /* A Directed Hypervisor Doorbell message is sent only if the
> +     * message type is 5. All other types are reserved and the
> +     * instruction is a no-op */
> +    return msg == DBELL_TYPE_DBELL_SERVER ? PPC_INTERRUPT_HDOORBELL : -1;
> +}
> +
> +void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
> +{
> +    int irq = book3s_dbell2irq(rb);
> +
> +    if (irq < 0) {
> +        return;
> +    }
> +
> +    env->pending_interrupts &= ~(1 << irq);
> +}
> +
> +void helper_book3s_msgsnd(target_ulong rb)
> +{
> +    int irq = book3s_dbell2irq(rb);
> +    int pir = rb & DBELL_PROCIDTAG_MASK;
> +    CPUState *cs;
> +
> +    if (irq < 0) {
> +        return;
> +    }
> +
> +    qemu_mutex_lock_iothread();
> +    CPU_FOREACH(cs) {
> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> +        CPUPPCState *cenv = &cpu->env;
> +
> +        /* TODO: broadcast message to all threads of the same  processor */
> +        if (cenv->spr_cb[SPR_PIR].default_value == pir) {
> +            cenv->pending_interrupts |= 1 << irq;
> +            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> +        }
> +    }
> +    qemu_mutex_unlock_iothread();
> +}
>  #endif
> diff --git a/target/ppc/helper.h b/target/ppc/helper.h
> index bb6a94a8b390..5b739179b8b5 100644
> --- a/target/ppc/helper.h
> +++ b/target/ppc/helper.h
> @@ -679,6 +679,8 @@ DEF_HELPER_FLAGS_3(store_sr, TCG_CALL_NO_RWG, void, env, tl, tl)
>  DEF_HELPER_FLAGS_1(602_mfrom, TCG_CALL_NO_RWG_SE, tl, tl)
>  DEF_HELPER_1(msgsnd, void, tl)
>  DEF_HELPER_2(msgclr, void, env, tl)
> +DEF_HELPER_1(book3s_msgsnd, void, tl)
> +DEF_HELPER_2(book3s_msgclr, void, env, tl)
>  #endif
>  
>  DEF_HELPER_4(dlmzb, tl, env, tl, tl, i32)
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 396f422cf407..4325aa90a6fa 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -6175,7 +6175,12 @@ static void gen_msgclr(DisasContext *ctx)
>      GEN_PRIV;
>  #else
>      CHK_HV;
> -    gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
> +    /* 64-bit server processors compliant with arch 2.x */
> +    if (ctx->insns_flags & PPC_SEGMENT_64B) {
> +        gen_helper_book3s_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
> +    } else {
> +        gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
> +    }
>  #endif /* defined(CONFIG_USER_ONLY) */
>  }
>  
> @@ -6185,10 +6190,24 @@ static void gen_msgsnd(DisasContext *ctx)
>      GEN_PRIV;
>  #else
>      CHK_HV;
> -    gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
> +    /* 64-bit server processors compliant with arch 2.x */
> +    if (ctx->insns_flags & PPC_SEGMENT_64B) {
> +        gen_helper_book3s_msgsnd(cpu_gpr[rB(ctx->opcode)]);
> +    } else {
> +        gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
> +    }
>  #endif /* defined(CONFIG_USER_ONLY) */
>  }
>  
> +static void gen_msgsync(DisasContext *ctx)
> +{
> +#if defined(CONFIG_USER_ONLY)
> +    GEN_PRIV;
> +#else
> +    CHK_HV;
> +#endif /* defined(CONFIG_USER_ONLY) */
> +    /* interpreted as no-op */
> +}
>  
>  #if defined(TARGET_PPC64)
>  static void gen_maddld(DisasContext *ctx)
> @@ -6669,6 +6688,8 @@ GEN_HANDLER2_E(msgsnd, "msgsnd", 0x1F, 0x0E, 0x06, 0x03ff0001,
>                 PPC_NONE, PPC2_PRCNTL),
>  GEN_HANDLER2_E(msgclr, "msgclr", 0x1F, 0x0E, 0x07, 0x03ff0001,
>                 PPC_NONE, PPC2_PRCNTL),
> +GEN_HANDLER2_E(msgsync, "msgsync", 0x1F, 0x16, 0x1B, 0x00000000,
> +               PPC_NONE, PPC2_PRCNTL),
>  GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
>  GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
>  GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
> diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
> index ab70b3a25c1d..87a23f0f6265 100644
> --- a/target/ppc/translate_init.c
> +++ b/target/ppc/translate_init.c
> @@ -8866,7 +8866,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
>                          PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
>                          PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
>                          PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
> -                        PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300;
> +                        PPC2_TM | PPC2_PM_ISA206 | PPC2_ISA300 | PPC2_PRCNTL;
>      pcc->msr_mask = (1ull << MSR_SF) |
>                      (1ull << MSR_TM) |
>                      (1ull << MSR_VR) |

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson