diff options
author | Richard Henderson <rth@twiddle.net> | 2011-04-28 10:40:08 -0700 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2011-10-08 08:49:09 -0700 |
commit | c781cf96e298b9134b05ed1e7ca981a929e08e77 (patch) | |
tree | 5820b562c7b9eab3a3f71dc640502a09b028d632 /hw/alpha_typhoon.c | |
parent | 034ebc2753e7d16879a91e4407c4e0706f63604e (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.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c index 4c97219f8c..c769fcc138 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); |