summaryrefslogtreecommitdiff
path: root/hw/hpet.c
diff options
context:
space:
mode:
authorBeth Kon <eak@us.ibm.com>2009-07-24 12:26:59 -0400
committerAnthony Liguori <aliguori@us.ibm.com>2009-07-27 14:08:23 -0500
commitce536cfd1c33bf1a59a02436a025ddc7ef3a63b6 (patch)
tree5476332d116224bfb12a5e470ebe9a67b4774185 /hw/hpet.c
parentbb53fc5394201c0cbe3c89a1c9fa5fbd6a3b832c (diff)
HPET fixes for reg writes
This patch addresses the problems found by Andriy Gapon: - The code was incorrectly overwriting the high order 32 bits of the timer and hpet config registers. This didn't show up in testing because linux and windows use hpet in legacy mode, where the high order 32 bits (advertising available interrupts) of the timer config register are ignored, and the high order 32 bits of the hpet config register are reserved and unused. - The mask for level-triggered interrupts was off by a bit. (hpet doesn't currently support level-triggered interrupts). In addition, I removed some unused #defines, and corrected the ioapic interrupt values advertised. I'd set this up early in hpet development and never went back to correct it, and no bugs resulted since linux and windows use hpet in legacy mode where available interrupts are ignored. Signed-off-by: Beth Kon <eak@us.ibm.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/hpet.c')
-rw-r--r--hw/hpet.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/hw/hpet.c b/hw/hpet.c
index 24aee6a2c..01b10aa59 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -371,7 +371,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
{
int i;
HPETState *s = (HPETState *)opaque;
- uint64_t old_val, new_val, index;
+ uint64_t old_val, new_val, val, index;
dprintf("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
index = addr;
@@ -387,8 +387,8 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
switch ((addr - 0x100) % 0x20) {
case HPET_TN_CFG:
dprintf("qemu: hpet_ram_writel HPET_TN_CFG\n");
- timer->config = hpet_fixup_reg(new_val, old_val,
- HPET_TN_CFG_WRITE_MASK);
+ val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
+ timer->config = (timer->config & 0xffffffff00000000ULL) | val;
if (new_val & HPET_TN_32BIT) {
timer->cmp = (uint32_t)timer->cmp;
timer->period = (uint32_t)timer->period;
@@ -456,8 +456,8 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
case HPET_ID:
return;
case HPET_CFG:
- s->config = hpet_fixup_reg(new_val, old_val,
- HPET_CFG_WRITE_MASK);
+ val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
+ s->config = (s->config & 0xffffffff00000000ULL) | val;
if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
/* Enable main counter and interrupt generation. */
s->hpet_offset = ticks_to_ns(s->hpet_counter)
@@ -541,8 +541,8 @@ static void hpet_reset(void *opaque) {
timer->tn = i;
timer->cmp = ~0ULL;
timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
- /* advertise availability of irqs 5,10,11 */
- timer->config |= 0x00000c20ULL << 32;
+ /* advertise availability of ioapic inti2 */
+ timer->config |= 0x00000004ULL << 32;
timer->state = s;
timer->period = 0ULL;
timer->wrap_flag = 0;