@@ -900,7 +900,11 @@ static void ppc_hw_interrupt(CPUPPCState *env)
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
- powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
+ if (is_book3s_arch2x(env)) {
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
+ } else {
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
+ }
return;
}
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
@@ -1221,39 +1225,30 @@ void helper_msgsnd(target_ulong rb)
}
/* Server Processor Control */
-static int book3s_dbell2irq(target_ulong rb)
-{
- int msg = rb & DBELL_TYPE_MASK;
+static bool dbell_type_server(target_ulong rb)
+{
/*
* 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;
+ return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
}
void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
{
- int irq = book3s_dbell2irq(rb);
-
- if (irq < 0) {
+ if (!dbell_type_server(rb)) {
return;
}
- env->pending_interrupts &= ~(1 << irq);
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
}
-void helper_book3s_msgsnd(target_ulong rb)
+static void book3s_msgsnd_common(int pir, int irq)
{
- 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);
@@ -1267,6 +1262,45 @@ void helper_book3s_msgsnd(target_ulong rb)
}
qemu_mutex_unlock_iothread();
}
+
+void helper_book3s_msgsnd(target_ulong rb)
+{
+ int pir = rb & DBELL_PROCIDTAG_MASK;
+
+ if (!dbell_type_server(rb)) {
+ return;
+ }
+
+ book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
+}
+
+#if defined(TARGET_PPC64)
+void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
+{
+ if (!dbell_type_server(rb)) {
+ return;
+ }
+
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
+}
+
+/*
+ * sends a message to other threads that are on the same
+ * multi-threaded processor
+ */
+void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
+{
+ int pir = env->spr_cb[SPR_PIR].default_value;
+
+ if (!dbell_type_server(rb)) {
+ return;
+ }
+
+ /* TODO: TCG supports only one thread */
+
+ book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
+}
+#endif
#endif
void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
@@ -657,6 +657,10 @@ DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
DEF_HELPER_FLAGS_2(store_purr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_2(store_ptcr, void, env, tl)
+DEF_HELPER_FLAGS_1(load_dpdes, TCG_CALL_NO_RWG, tl, env)
+DEF_HELPER_FLAGS_2(store_dpdes, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_2(book3s_msgsndp, void, env, tl)
+DEF_HELPER_2(book3s_msgclrp, void, env, tl)
#endif
DEF_HELPER_2(store_sdr1, void, env, tl)
DEF_HELPER_2(store_pidr, void, env, tl)
@@ -105,6 +105,42 @@ void helper_store_pcr(CPUPPCState *env, target_ulong value)
env->spr[SPR_PCR] = value & pcc->pcr_mask;
}
+
+/*
+ * DPDES register is shared. Each bit reflects the state of the
+ * doorbell interrupt of a thread of the same core.
+ */
+target_ulong helper_load_dpdes(CPUPPCState *env)
+{
+ target_ulong dpdes = 0;
+
+ /* TODO: TCG supports only one thread */
+ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
+ dpdes = 1;
+ }
+
+ return dpdes;
+}
+
+void helper_store_dpdes(CPUPPCState *env, target_ulong val)
+{
+ PowerPCCPU *cpu = env_archcpu(env);
+ CPUState *cs = CPU(cpu);
+
+ /* TODO: TCG supports only one thread */
+ if (val & ~0x1) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid DPDES register value "
+ TARGET_FMT_lx"\n", val);
+ return;
+ }
+
+ if (val & 0x1) {
+ env->pending_interrupts |= 1 << PPC_INTERRUPT_DOORBELL;
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
+ }
+}
#endif /* defined(TARGET_PPC64) */
void helper_store_pidr(CPUPPCState *env, target_ulong val)
@@ -6645,6 +6645,28 @@ static void gen_msgsnd(DisasContext *ctx)
#endif /* defined(CONFIG_USER_ONLY) */
}
+#if defined(TARGET_PPC64)
+static void gen_msgclrp(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ GEN_PRIV;
+#else
+ CHK_SV;
+ gen_helper_book3s_msgclrp(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+#endif /* defined(CONFIG_USER_ONLY) */
+}
+
+static void gen_msgsndp(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ GEN_PRIV;
+#else
+ CHK_SV;
+ gen_helper_book3s_msgsndp(cpu_env, cpu_gpr[rB(ctx->opcode)]);
+#endif /* defined(CONFIG_USER_ONLY) */
+}
+#endif
+
static void gen_msgsync(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
@@ -7187,6 +7209,10 @@ GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC),
GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
PPC2_ISA300),
GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER2_E(msgsndp, "msgsndp", 0x1F, 0x0E, 0x04, 0x03ff0001,
+ PPC_NONE, PPC2_ISA207S),
+GEN_HANDLER2_E(msgclrp, "msgclrp", 0x1F, 0x0E, 0x05, 0x03ff0001,
+ PPC_NONE, PPC2_ISA207S),
#endif
#undef GEN_INT_ARITH_ADD
@@ -464,6 +464,17 @@ static void spr_write_pcr(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_pcr(cpu_env, cpu_gpr[gprn]);
}
+
+/* DPDES */
+static void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn)
+{
+ gen_helper_load_dpdes(cpu_gpr[gprn], cpu_env);
+}
+
+static void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn)
+{
+ gen_helper_store_dpdes(cpu_env, cpu_gpr[gprn]);
+}
#endif
#endif
@@ -8238,10 +8249,11 @@ static void gen_spr_power8_dpdes(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
/* Directed Privileged Door-bell Exception State, used for IPI */
- spr_register(env, SPR_DPDES, "DPDES",
- SPR_NOACCESS, SPR_NOACCESS,
- &spr_read_generic, SPR_NOACCESS,
- 0x00000000);
+ spr_register_kvm_hv(env, SPR_DPDES, "DPDES",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_dpdes, SPR_NOACCESS,
+ &spr_read_dpdes, &spr_write_dpdes,
+ KVM_REG_PPC_DPDES, 0x00000000);
#endif
}