aboutsummaryrefslogtreecommitdiffstats
path: root/hw/alpha_typhoon.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2011-04-28 10:40:08 -0700
committerRichard Henderson <rth@twiddle.net>2011-10-08 08:49:09 -0700
commitc781cf96e298b9134b05ed1e7ca981a929e08e77 (patch)
tree5820b562c7b9eab3a3f71dc640502a09b028d632 /hw/alpha_typhoon.c
parent034ebc2753e7d16879a91e4407c4e0706f63604e (diff)
target-alpha: Add high-resolution access to wall clock and an alarm.
The alarm is a fully general one-shot time comparator, which will be usable under Linux as a hrtimer source. It's much more flexible than the RTC source available on real hardware. The wall clock allows the guest access to the host timekeeping. Much like the KVM wall clock source for other guests. Both are accessed via the PALcode Cserve entry point. Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'hw/alpha_typhoon.c')
-rw-r--r--hw/alpha_typhoon.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 4c97219f8..c769fcc13 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -681,6 +681,16 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
}
}
+static void typhoon_alarm_timer(void *opaque)
+{
+ TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
+ int cpu = (uintptr_t)opaque & 3;
+
+ /* Set the ITI bit for this cpu. */
+ s->cchip.misc |= 1 << (cpu + 4);
+ cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
+}
+
PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
CPUState *cpus[4], pci_map_irq_fn sys_map_irq)
{
@@ -692,6 +702,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
PCIHostState *p;
TyphoonState *s;
PCIBus *b;
+ int i;
dev = qdev_create(NULL, "typhoon-pcihost");
qdev_init_nofail(dev);
@@ -700,7 +711,15 @@ PCIBus *typhoon_init(ram_addr_t ram_size, qemu_irq *p_rtc_irq,
s = container_of(p, TyphoonState, host);
/* Remember the CPUs so that we can deliver interrupts to them. */
- memcpy(s->cchip.cpu, cpus, 4 * sizeof(CPUState *));
+ for (i = 0; i < 4; i++) {
+ CPUState *env = cpus[i];
+ s->cchip.cpu[i] = env;
+ if (env) {
+ env->alarm_timer = qemu_new_timer_ns(rtc_clock,
+ typhoon_alarm_timer,
+ (void *)((uintptr_t)s + i));
+ }
+ }
*p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);