[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 58/77] ppc: Initial HDEC support
From: |
Benjamin Herrenschmidt |
Subject: |
[Qemu-ppc] [PATCH 58/77] ppc: Initial HDEC support |
Date: |
Wed, 11 Nov 2015 11:28:11 +1100 |
The current behaviour isn't completely right, as for the DEC, we
don't properly re-arm when wrapping around, but I will fix this
in a separate patch.
Signed-off-by: Benjamin Herrenschmidt <address@hidden>
---
hw/ppc/ppc.c | 17 ++++++++++++-----
target-ppc/excp_helper.c | 22 ++++++++++++----------
target-ppc/helper.h | 2 ++
target-ppc/timebase_helper.c | 10 ++++++++++
target-ppc/translate_init.c | 30 ++++++++++++++++++++++++++++++
5 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 3b14f09..ac3f65c 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -698,9 +698,18 @@ static inline void cpu_ppc_decr_lower(PowerPCCPU *cpu)
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
{
+ CPUPPCState *env = &cpu->env;
+
/* Raise it */
- LOG_TB("raise decrementer exception\n");
- ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+ LOG_TB("raise hv decrementer exception\n");
+
+ /* The architecture specifies that we don't deliver HDEC
+ * interrupts in a PM state. Not only they don't cause a
+ * wakeup but they also get effectively discarded.
+ */
+ if (!env->in_pm_state) {
+ ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
+ }
}
static inline void cpu_ppc_hdecr_lower(PowerPCCPU *cpu)
@@ -927,9 +936,7 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t
freq)
}
/* Create new timer */
tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb,
cpu);
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor decrementer
- */
+ if (env->has_hv_mode) {
tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
&cpu_ppc_hdecr_cb,
cpu);
} else {
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index eb65eee..28a529a 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -753,7 +753,6 @@ void ppc_cpu_do_interrupt(CPUState *cs)
static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
- int hdice;
#if 0
CPUState *cs = CPU(cpu);
@@ -782,15 +781,13 @@ static void ppc_hw_interrupt(CPUPPCState *env)
return;
}
#endif
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor mode */
- hdice = env->spr[SPR_LPCR] & 1;
- } else {
- hdice = 0;
- }
- if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
- /* Hypervisor decrementer exception */
- if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+ /* Hypervisor decrementer exception */
+ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
+ /* LPCR will be clear when not supported so this will work */
+ bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
+ if ((msr_ee != 0 || msr_hv == 0) && hdice) {
+ /* HDEC clears on delivery */
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
@@ -942,6 +939,11 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t
insn)
cs->halted = 1;
env->in_pm_state = true;
+ /* The architecture specifies that HDEC interrupts are
+ * discarded in PM states
+ */
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
+
/* Technically, nap doesn't set EE, but if we don't set it
* then ppc_hw_interrupt() won't deliver. We could add some
* other tests there based on LPCR but it's simpler to just
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 23889fe..9890920 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -598,6 +598,8 @@ DEF_HELPER_2(store_601_rtcl, void, env, tl)
DEF_HELPER_2(store_601_rtcu, void, env, tl)
DEF_HELPER_1(load_decr, tl, env)
DEF_HELPER_2(store_decr, void, env, tl)
+DEF_HELPER_1(load_hdecr, tl, env)
+DEF_HELPER_2(store_hdecr, void, env, tl)
DEF_HELPER_2(store_hid0_601, void, env, tl)
DEF_HELPER_3(store_403_pbr, void, env, i32, tl)
DEF_HELPER_1(load_40x_pit, tl, env)
diff --git a/target-ppc/timebase_helper.c b/target-ppc/timebase_helper.c
index 865dcbe..798b803 100644
--- a/target-ppc/timebase_helper.c
+++ b/target-ppc/timebase_helper.c
@@ -100,6 +100,16 @@ void helper_store_decr(CPUPPCState *env, target_ulong val)
cpu_ppc_store_decr(env, val);
}
+target_ulong helper_load_hdecr(CPUPPCState *env)
+{
+ return cpu_ppc_load_hdecr(env);
+}
+
+void helper_store_hdecr(CPUPPCState *env, target_ulong val)
+{
+ cpu_ppc_store_hdecr(env, val);
+}
+
target_ulong helper_load_40x_pit(CPUPPCState *env)
{
return load_40x_pit(env);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 25f5b18..06061e2 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -292,6 +292,32 @@ static void spr_read_purr (DisasContext *ctx, int gprn,
int sprn)
{
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
}
+
+/* HDECR */
+static void spr_read_hdecr (DisasContext *ctx, int gprn, int sprn)
+{
+ if (ctx->tb->cflags & CF_USE_ICOUNT) {
+ gen_io_start();
+ }
+ gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
+ if (ctx->tb->cflags & CF_USE_ICOUNT) {
+ gen_io_end();
+ gen_stop_exception(ctx);
+ }
+}
+
+static void spr_write_hdecr (DisasContext *ctx, int sprn, int gprn)
+{
+ if (ctx->tb->cflags & CF_USE_ICOUNT) {
+ gen_io_start();
+ }
+ gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
+ if (ctx->tb->cflags & CF_USE_ICOUNT) {
+ gen_io_end();
+ gen_stop_exception(ctx);
+ }
+}
+
#endif
#endif
@@ -7716,6 +7742,10 @@ static void gen_spr_power5p_lpar(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_lpcr,
KVM_REG_PPC_LPCR, LPCR_LPES0 | LPCR_LPES1);
+ spr_register_hv(env, SPR_HDEC, "HDEC",
+ SPR_NOACCESS, SPR_NOACCESS,
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_hdecr, &spr_write_hdecr, 0);
#endif
}
--
2.5.0
- [Qemu-ppc] [PATCH 49/77] ppc/pnv: Create a default PCI layout, (continued)
- [Qemu-ppc] [PATCH 49/77] ppc/pnv: Create a default PCI layout, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 51/77] ppc: Use a helper to filter writes to LPCR, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 53/77] ppc: Add proper real mode translation support, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 52/77] ppc: Cosmetic, align some comments, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 63/77] ppc: Initialize AMOR in PAPR mode, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 57/77] ppc: Enforce setting MSR:EE, IR and DR when MSR:PR is set, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 61/77] ppc: SPURR & PURR are HV writeable and privileged, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 55/77] ppc/pnv+spapr: Add "ibm, pa-features" property to the device-tree, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 56/77] ppc: Fix conditions for delivering external interrupts to a guest, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 54/77] ppc: Fix 64K pages support in full emulation, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 58/77] ppc: Initial HDEC support,
Benjamin Herrenschmidt <=
- [Qemu-ppc] [PATCH 59/77] ppc: Add placeholder SPRs for DPDES and DHDES on P8, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 62/77] ppc: Add dummy SPR_IC for POWER8, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 60/77] ppc: LPCR is a HV resource, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 64/77] ppc: Fix writing to AMR/UAMOR, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 65/77] ppc: Add POWER8 IAMR register, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 67/77] ppc: Add dummy write to VTB, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 66/77] ppc: Add a few more P8 PMU SPRs, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 68/77] ppc: Add dummy POWER8 MPPR register, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 72/77] ppc: A couple more dummy POWER8 Book4 regs, Benjamin Herrenschmidt, 2015/11/10
- [Qemu-ppc] [PATCH 77/77] ppc: Fix CFAR updates, Benjamin Herrenschmidt, 2015/11/10