Commit ce536cfd1c33bf1a59a02436a025ddc7ef3a63b6

Authored by Beth Kon
Committed by Anthony Liguori
1 parent bb53fc53

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>
Showing 2 changed files with 8 additions and 13 deletions
hw/hpet.c
... ... @@ -371,7 +371,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
371 371 {
372 372 int i;
373 373 HPETState *s = (HPETState *)opaque;
374   - uint64_t old_val, new_val, index;
  374 + uint64_t old_val, new_val, val, index;
375 375  
376 376 dprintf("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
377 377 index = addr;
... ... @@ -387,8 +387,8 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
387 387 switch ((addr - 0x100) % 0x20) {
388 388 case HPET_TN_CFG:
389 389 dprintf("qemu: hpet_ram_writel HPET_TN_CFG\n");
390   - timer->config = hpet_fixup_reg(new_val, old_val,
391   - HPET_TN_CFG_WRITE_MASK);
  390 + val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
  391 + timer->config = (timer->config & 0xffffffff00000000ULL) | val;
392 392 if (new_val & HPET_TN_32BIT) {
393 393 timer->cmp = (uint32_t)timer->cmp;
394 394 timer->period = (uint32_t)timer->period;
... ... @@ -456,8 +456,8 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
456 456 case HPET_ID:
457 457 return;
458 458 case HPET_CFG:
459   - s->config = hpet_fixup_reg(new_val, old_val,
460   - HPET_CFG_WRITE_MASK);
  459 + val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
  460 + s->config = (s->config & 0xffffffff00000000ULL) | val;
461 461 if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
462 462 /* Enable main counter and interrupt generation. */
463 463 s->hpet_offset = ticks_to_ns(s->hpet_counter)
... ... @@ -541,8 +541,8 @@ static void hpet_reset(void *opaque) {
541 541 timer->tn = i;
542 542 timer->cmp = ~0ULL;
543 543 timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
544   - /* advertise availability of irqs 5,10,11 */
545   - timer->config |= 0x00000c20ULL << 32;
  544 + /* advertise availability of ioapic inti2 */
  545 + timer->config |= 0x00000004ULL << 32;
546 546 timer->state = s;
547 547 timer->period = 0ULL;
548 548 timer->wrap_flag = 0;
... ...
hw/hpet_emul.h
... ... @@ -18,12 +18,7 @@
18 18  
19 19 #define FS_PER_NS 1000000
20 20 #define HPET_NUM_TIMERS 3
21   -#define HPET_TIMER_TYPE_LEVEL 1
22   -#define HPET_TIMER_TYPE_EDGE 0
23   -#define HPET_TIMER_DELIVERY_APIC 0
24   -#define HPET_TIMER_DELIVERY_FSB 1
25   -#define HPET_TIMER_CAP_FSB_INT_DEL (1 << 15)
26   -#define HPET_TIMER_CAP_PER_INT (1 << 4)
  21 +#define HPET_TIMER_TYPE_LEVEL 0x002
27 22  
28 23 #define HPET_CFG_ENABLE 0x001
29 24 #define HPET_CFG_LEGACY 0x002
... ...