From 1414c75d54e0e8769129beb92bc784338090afda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 16 Jan 2018 08:41:55 +0100 Subject: target/ppc: fix doorbell and hypervisor doorbell definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f03a1af581b9 ("ppc: Fix POWER7 and POWER8 exception definitions") introduced definitions for the server doorbell exceptions by reusing the embedded definitions but this adds complexity in the powerpc_excp() routine. Let's introduce specific definitions for the Server doorbells exception. Signed-off-by: Cédric Le Goater Signed-off-by: David Gibson --- target/ppc/cpu.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'target') diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 14aaa87..b8f4dfc 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -140,9 +140,6 @@ enum { POWERPC_EXCP_HYPPRIV = 41, /* Embedded hypervisor priv instruction */ /* Vectors 42 to 63 are reserved */ /* Exceptions defined in the PowerPC server specification */ - /* Server doorbell variants */ -#define POWERPC_EXCP_SDOOR POWERPC_EXCP_GDOORI -#define POWERPC_EXCP_SDOOR_HV POWERPC_EXCP_DOORI POWERPC_EXCP_RESET = 64, /* System reset exception */ POWERPC_EXCP_DSEG = 65, /* Data segment exception */ POWERPC_EXCP_ISEG = 66, /* Instruction segment exception */ @@ -189,8 +186,11 @@ enum { POWERPC_EXCP_HV_EMU = 96, /* HV emulation assistance */ POWERPC_EXCP_HV_MAINT = 97, /* HMI */ POWERPC_EXCP_HV_FU = 98, /* Hypervisor Facility unavailable */ + /* Server doorbell variants */ + POWERPC_EXCP_SDOOR = 99, + POWERPC_EXCP_SDOOR_HV = 100, /* EOL */ - POWERPC_EXCP_NB = 99, + POWERPC_EXCP_NB = 101, /* QEMU exceptions: used internally during code translation */ POWERPC_EXCP_STOP = 0x200, /* stop translation */ POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */ -- cgit v1.1 From ebca5e6d5ec2f1cf6c886a114e161261af28dc0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 16 Jan 2018 08:41:56 +0100 Subject: target/ppc: msgsnd and msgclr instructions need hypervisor privilege MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédric Le Goater Signed-off-by: David Gibson --- target/ppc/translate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'target') diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 0ef21cc..396f422 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6174,7 +6174,7 @@ static void gen_msgclr(DisasContext *ctx) #if defined(CONFIG_USER_ONLY) GEN_PRIV; #else - CHK_SV; + CHK_HV; gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]); #endif /* defined(CONFIG_USER_ONLY) */ } @@ -6184,7 +6184,7 @@ static void gen_msgsnd(DisasContext *ctx) #if defined(CONFIG_USER_ONLY) GEN_PRIV; #else - CHK_SV; + CHK_HV; gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]); #endif /* defined(CONFIG_USER_ONLY) */ } -- cgit v1.1 From b62b368627ea160d2bfd7886aa690047480036a0 Mon Sep 17 00:00:00 2001 From: "pbonzini@redhat.com" Date: Sun, 17 Dec 2017 06:49:53 +0100 Subject: target-ppc: optimize cmp translation We know that only one bit (in addition to SO) is going to be set in the condition register, so do two movconds instead of three setconds, three shifts and two ORs. For ppc64-linux-user, the code size reduction is around 5% and the performance improvement slightly less than 10%. For softmmu, the improvement is around 5%. Signed-off-by: Paolo Bonzini Signed-off-by: David Gibson --- target/ppc/translate.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'target') diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 396f422..bcd36d5 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -605,27 +605,22 @@ static opc_handler_t invalid_handler = { static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf) { TCGv t0 = tcg_temp_new(); - TCGv_i32 t1 = tcg_temp_new_i32(); - - tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so); - - tcg_gen_setcond_tl((s ? TCG_COND_LT: TCG_COND_LTU), t0, arg0, arg1); - tcg_gen_trunc_tl_i32(t1, t0); - tcg_gen_shli_i32(t1, t1, CRF_LT_BIT); - tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); + TCGv t1 = tcg_temp_new(); + TCGv_i32 t = tcg_temp_new_i32(); - tcg_gen_setcond_tl((s ? TCG_COND_GT: TCG_COND_GTU), t0, arg0, arg1); - tcg_gen_trunc_tl_i32(t1, t0); - tcg_gen_shli_i32(t1, t1, CRF_GT_BIT); - tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); + tcg_gen_movi_tl(t0, CRF_EQ); + tcg_gen_movi_tl(t1, CRF_LT); + tcg_gen_movcond_tl((s ? TCG_COND_LT : TCG_COND_LTU), t0, arg0, arg1, t1, t0); + tcg_gen_movi_tl(t1, CRF_GT); + tcg_gen_movcond_tl((s ? TCG_COND_GT : TCG_COND_GTU), t0, arg0, arg1, t1, t0); - tcg_gen_setcond_tl(TCG_COND_EQ, t0, arg0, arg1); - tcg_gen_trunc_tl_i32(t1, t0); - tcg_gen_shli_i32(t1, t1, CRF_EQ_BIT); - tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t1); + tcg_gen_trunc_tl_i32(t, t0); + tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so); + tcg_gen_or_i32(cpu_crf[crf], cpu_crf[crf], t); tcg_temp_free(t0); - tcg_temp_free_i32(t1); + tcg_temp_free(t1); + tcg_temp_free_i32(t); } static inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf) -- cgit v1.1 From 7af1e7b022641e4cc330a75ab50fa64683fe4847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Thu, 18 Jan 2018 15:54:03 +0100 Subject: target/ppc: add support for hypervisor doorbells on book3s CPUs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: David Gibson --- 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(-) (limited to 'target') diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index b8f4dfc..603a38c 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 4e548a4..c092fbe 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 bb6a94a..5b73917 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 bcd36d5..4132f67 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6170,7 +6170,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) */ } @@ -6180,10 +6185,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) @@ -6664,6 +6683,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 70ff15a..55c99c9 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) | -- cgit v1.1