From: Yodel Eldar <yodel.eldar@yodel.dev>
This commit creates a QEMU-specific (non-standard) MMIO register
in Typhoon's Cchip to replace helper_set_alarm() and to move
the QEMUTimer pointer, alarm_timer, out of the Alpha CPU and into
the chipset code.
Currently, PALcode writes to the QEMU-specific, synthetic
Processor Register (index 251) and triggers the invocation of
helper_set_alarm() as a side effect in QEMU, thereby setting
the timer alarm expiration value.
This works, because the AlphaCPU contains the QEMUTimer and
CPUAlphaState stores the alarm expiration value; however, the timer
alarm callback resides in and is specific to the Typhoon chipset,
thus the CPU and the chipset are entangled.
By designating the currently unused offset (0x7c0) of Cchip as the
location of the timer alarm expiration, we can disentangle and
better encapsulate both.
Suggested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Yodel Eldar <yodel.eldar@yodel.dev>
---
Notes:
The patch to the palcode-clipper binary that follows this
one is necessary for this patch to work; I've left the
diff to the source in the notes of it for reproduction.
Philippe:
Thanks, again, for the suggestion of decoupling the CPU from
the Typhoon using IRQ lines. In my response, I guessed that
getting the CPU index would be trickier than moving the timer
into TyphoonState; perhaps you'll find it amusing (as I do)
that it appears I had that backwards (due to the PALcode
peculiarity)!
The remaining CPU interrupts will be refactored in v2 of that
series.
hw/alpha/dp264.c | 4 ++++
hw/alpha/typhoon.c | 38 ++++++++++++++++++++++++++++++++------
target/alpha/cpu.c | 17 +++++++++++++++++
target/alpha/cpu.h | 6 ------
target/alpha/helper.h | 1 -
target/alpha/sys_helper.c | 12 ------------
target/alpha/translate.c | 11 -----------
7 files changed, 53 insertions(+), 36 deletions(-)
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index ce2f8765cd..8e63b48a02 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -71,6 +71,10 @@ static void clipper_init(MachineState *machine)
memset(cpus, 0, sizeof(cpus));
for (i = 0; i < smp_cpus; ++i) {
cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
+
+ qdev_connect_gpio_out_named(DEVICE(typhoon_obj), "cpu-irq", i,
+ qdev_get_gpio_in_named(DEVICE(cpus[i]),
+ "timer-irq", 0));
}
/*
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index 5dadfa7691..a40f690ed1 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -26,6 +26,9 @@ typedef struct TyphoonCchip {
uint64_t dim[4];
uint32_t iic[4];
AlphaCPU *cpu[4];
+ qemu_irq cpu_irq[4];
+ QEMUTimer *alarm_timer[4];
+ uint64_t alarm_expire[4];
} TyphoonCchip;
typedef struct TyphoonWindow {
@@ -187,6 +190,14 @@ static MemTxResult cchip_read(void *opaque, hwaddr addr,
/* PWR: Power Management Control. */
break;
+ case 0x07c0: {
+ /* ALRM: QEMU-specific Timer Alarm Register */
+ uint64_t cpu_index = attrs.requester_id & 3;
+
+ ret = s->cchip.alarm_expire[cpu_index];
+
+ break;
+ }
case 0x0c00: /* CMONCTLA */
case 0x0c40: /* CMONCTLB */
case 0x0c80: /* CMONCNT01 */
@@ -352,7 +363,7 @@ static MemTxResult cchip_write(void *opaque, hwaddr addr,
/* ITI can only be cleared by the write. */
if ((newval & (1 << (i + 4))) == 0) {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
+ qemu_set_irq(s->cchip.cpu_irq[i], 0);
}
}
}
@@ -439,6 +450,19 @@ static MemTxResult cchip_write(void *opaque, hwaddr addr,
/* PWR: Power Management Control. */
break;
+ case 0x07c0: {
+ /* ALRM: QEMU-specific Timer Alarm Register */
+ uint64_t cpu_index = attrs.requester_id & 3;
+ QEMUTimer *alarm_timer = s->cchip.alarm_timer[cpu_index];
+
+ if (val) {
+ s->cchip.alarm_expire[cpu_index] = val;
+ timer_mod(alarm_timer, val);
+ } else {
+ timer_del(alarm_timer);
+ }
+ break;
+ }
case 0x0c00: /* CMONCTLA */
case 0x0c40: /* CMONCTLB */
case 0x0c80: /* CMONCNT01 */
@@ -801,7 +825,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
/* Set the ITI bit for this cpu. */
s->cchip.misc |= 1 << (i + 4);
/* And signal the interrupt. */
- cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
+ qemu_set_irq(s->cchip.cpu_irq[i], 1);
}
}
}
@@ -814,7 +838,7 @@ static void typhoon_alarm_timer(void *opaque)
/* Set the ITI bit for this cpu. */
s->cchip.misc |= 1 << (cpu + 4);
- cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
+ qemu_set_irq(s->cchip.cpu_irq[cpu], 1);
}
static void typhoon_pcihost_instance_init(Object *obj)
@@ -823,6 +847,8 @@ static void typhoon_pcihost_instance_init(Object *obj)
s->cchip.misc = 0x800000000ull; /* Revision: Typhoon. */
s->pchip.win[3].wba = 2; /* Window 3 SG always enabled. */
+
+ qdev_init_gpio_out_named(DEVICE(s), s->cchip.cpu_irq, "cpu-irq", 4);
}
PCIBus *typhoon_init(MemoryRegion *ram, qemu_irq *p_isa_irq,
@@ -843,9 +869,9 @@ PCIBus *typhoon_init(MemoryRegion *ram, qemu_irq *p_isa_irq,
AlphaCPU *cpu = cpus[i];
s->cchip.cpu[i] = cpu;
if (cpu != NULL) {
- cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- typhoon_alarm_timer,
- (void *)((uintptr_t)s + i));
+ s->cchip.alarm_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ typhoon_alarm_timer,
+ (void *)((uintptr_t)s + i));
}
}
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index ff053043a3..7f908a98c0 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -27,6 +27,7 @@
#include "exec/target_page.h"
#include "accel/tcg/cpu-ops.h"
#include "fpu/softfloat.h"
+#include "hw/core/cpu.h"
static void alpha_cpu_set_pc(CPUState *cs, vaddr value)
@@ -203,10 +204,26 @@ static void ev67_cpu_initfn(Object *obj)
cpu_env(CPU(obj))->amask |= AMASK_CIX | AMASK_PREFETCH;
}
+#ifndef CONFIG_USER_ONLY
+static void alpha_cpu_irq_handler(void *opaque, int irq, int level)
+{
+ CPUState *cs = CPU(opaque);
+
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_TIMER);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
+ }
+}
+#endif
+
static void alpha_cpu_initfn(Object *obj)
{
CPUAlphaState *env = cpu_env(CPU(obj));
+#ifndef CONFIG_USER_ONLY
+ qdev_init_gpio_in_named(DEVICE(obj), alpha_cpu_irq_handler, "timer-irq", 1);
+#endif
/* TODO all this should be done in reset, not init */
env->lock_addr = -1;
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 45944e46b5..1ae1c40ce9 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -241,9 +241,6 @@ typedef struct CPUArchState {
uint64_t scratch[24];
#endif
- /* This alarm doesn't exist in real hardware; we wish it did. */
- uint64_t alarm_expire;
-
int error_code;
uint32_t features;
@@ -261,9 +258,6 @@ struct ArchCPU {
CPUState parent_obj;
CPUAlphaState env;
-
- /* This alarm doesn't exist in real hardware; we wish it did. */
- QEMUTimer *alarm_timer;
};
/**
diff --git a/target/alpha/helper.h b/target/alpha/helper.h
index 954a5c8294..c76b20eb8d 100644
--- a/target/alpha/helper.h
+++ b/target/alpha/helper.h
@@ -96,5 +96,4 @@ DEF_HELPER_1(whami, i64, env)
DEF_HELPER_FLAGS_0(get_vmtime, TCG_CALL_NO_RWG, i64)
DEF_HELPER_FLAGS_0(get_walltime, TCG_CALL_NO_RWG, i64)
-DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_NO_RWG, void, env, i64)
#endif
diff --git a/target/alpha/sys_helper.c b/target/alpha/sys_helper.c
index 0e0a619975..73f26a81d1 100644
--- a/target/alpha/sys_helper.c
+++ b/target/alpha/sys_helper.c
@@ -56,18 +56,6 @@ uint64_t helper_get_walltime(void)
return qemu_clock_get_ns(rtc_clock);
}
-void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
-{
- AlphaCPU *cpu = env_archcpu(env);
-
- if (expire) {
- env->alarm_expire = expire;
- timer_mod(cpu->alarm_timer, expire);
- } else {
- timer_del(cpu->alarm_timer);
- }
-}
-
uint64_t HELPER(whami)(CPUAlphaState *env)
{
return env_cpu(env)->cpu_index;
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 4d22d7d5a4..cfe84f28bf 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -1196,9 +1196,6 @@ static int cpu_pr_data(int pr)
case 40 ... 63:
return offsetof(CPUAlphaState, scratch[pr - 40]);
-
- case 251:
- return offsetof(CPUAlphaState, alarm_expire);
}
return 0;
}
@@ -1280,14 +1277,6 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv_i64 vb, int regno)
gen_helper_halt(vb);
return DISAS_PC_STALE;
- case 251:
- /* ALARM */
- if (translator_io_start(&ctx->base)) {
- ret = DISAS_PC_STALE;
- }
- gen_helper_set_alarm(tcg_env, vb);
- break;
-
case 7:
/* PALBR */
tcg_gen_st_i64(vb, tcg_env, offsetof(CPUAlphaState, palbr));
--
2.53.0
© 2016 - 2026 Red Hat, Inc.