aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/ppc/cpu.h16
-rw-r--r--target/ppc/excp_helper.c52
-rw-r--r--target/ppc/helper.h2
-rw-r--r--target/ppc/translate.c58
-rw-r--r--target/ppc/translate_init.c2
5 files changed, 102 insertions, 28 deletions
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 14aaa87..603a38c 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 */
@@ -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 0ef21cc..4132f67 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)
@@ -6174,8 +6169,13 @@ static void gen_msgclr(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
GEN_PRIV;
#else
- CHK_SV;
- gen_helper_msgclr(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+ CHK_HV;
+ /* 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) */
}
@@ -6184,11 +6184,25 @@ static void gen_msgsnd(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
GEN_PRIV;
#else
- CHK_SV;
- gen_helper_msgsnd(cpu_gpr[rB(ctx->opcode)]);
+ CHK_HV;
+ /* 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 +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) |