All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements
@ 2010-06-06  8:10 Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 01/16] hpet: Catch out-of-bounds timer access Jan Kiszka
                   ` (16 more replies)
  0 siblings, 17 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: blue Swirl, Paul Brook, Gleb Natapov, Juan Quintela

Second round, specifically adressing:
 - IRQMsg framework to refactor existing de-coalescing code
 - RTC IRQ output as GPIO pin (routed depening on HPET or -no-hpet)
 - ISA reservation for RTC IRQ

If discussion around IRQMsg and de-coalescing happens to continue, I
would suggest to merge patches 1..7 as they are likely uncontroversial
and also fix bugs.

Jan Kiszka (16):
  hpet: Catch out-of-bounds timer access
  hpet: Coding style cleanups and some refactorings
  hpet: Silence warning on write to running main counter
  hpet: Move static timer field initialization
  hpet: Convert to qdev
  hpet: Start/stop timer when HPET_TN_ENABLE is modified
  monitor/QMP: Drop info hpet / query-hpet
  Pass IRQ object on handler invocation
  Enable message delivery via IRQs
  x86: Refactor RTC IRQ coalescing workaround
  hpet/rtc: Rework RTC IRQ replacement by HPET
  hpet: Drop static state
  hpet: Add support for level-triggered interrupts
  vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8
  hpet: Make number of timers configurable
  hpet: Add MSI support

 QMP/vm-info             |    2 +-
 hw/acpi_piix4.c         |    3 +-
 hw/apic.c               |   66 +++---
 hw/apic.h               |   11 +-
 hw/arm11mpcore.c        |   12 +-
 hw/arm_gic.c            |   18 +-
 hw/arm_pic.c            |    6 +-
 hw/arm_timer.c          |    4 +-
 hw/bitbang_i2c.c        |    4 +-
 hw/bt-hci-csr.c         |    2 +-
 hw/cbus.c               |    6 +-
 hw/cris_pic_cpu.c       |    4 +-
 hw/esp.c                |    2 +-
 hw/etraxfs_pic.c        |   16 +-
 hw/fdc.c                |    2 +-
 hw/heathrow_pic.c       |    3 +-
 hw/hpet.c               |  595 ++++++++++++++++++++++++++++++-----------------
 hw/hpet_emul.h          |   46 +---
 hw/hw.h                 |   10 +
 hw/i8259.c              |   28 ++-
 hw/ide/cmd646.c         |    2 +-
 hw/ide/microdrive.c     |    2 +-
 hw/integratorcp.c       |   10 +-
 hw/ioapic.c             |   22 ++-
 hw/irq.c                |   48 ++++-
 hw/irq.h                |   42 +++-
 hw/lance.c              |    2 +-
 hw/max7310.c            |    2 +-
 hw/mc146818rtc.c        |  111 +++++-----
 hw/mc146818rtc.h        |    4 +-
 hw/mcf5206.c            |    6 +-
 hw/mcf_intc.c           |   14 +-
 hw/microblaze_pic_cpu.c |    5 +-
 hw/mips_int.c           |   10 +-
 hw/mips_jazz.c          |    4 +-
 hw/mips_malta.c         |    4 +-
 hw/mips_r4k.c           |    2 +-
 hw/mst_fpga.c           |   10 +-
 hw/musicpal.c           |   16 +-
 hw/nseries.c            |    4 +-
 hw/omap.h               |    2 +-
 hw/omap1.c              |   34 ++--
 hw/omap2.c              |    8 +-
 hw/omap_dma.c           |    8 +-
 hw/omap_mmc.c           |    2 +-
 hw/openpic.c            |    6 +-
 hw/palm.c               |    2 +-
 hw/pc.c                 |   59 ++++--
 hw/pc.h                 |    8 +-
 hw/pci.c                |    4 +-
 hw/pl061.c              |    4 +-
 hw/pl190.c              |    6 +-
 hw/ppc.c                |    8 +-
 hw/ppc4xx_devs.c        |    2 +-
 hw/ppc_prep.c           |    4 +-
 hw/pxa2xx.c             |    2 +-
 hw/pxa2xx_gpio.c        |    2 +-
 hw/pxa2xx_pcmcia.c      |    3 +-
 hw/pxa2xx_pic.c         |   10 +-
 hw/r2d.c                |    2 +-
 hw/rc4030.c             |    7 +-
 hw/sbi.c                |    2 +-
 hw/sh_intc.c            |    4 +-
 hw/sh_intc.h            |    2 +-
 hw/sharpsl.h            |    1 -
 hw/slavio_intctl.c      |   16 +-
 hw/slavio_misc.c        |    3 +-
 hw/sparc32_dma.c        |    2 +-
 hw/spitz.c              |   14 +-
 hw/ssd0323.c            |    2 +-
 hw/stellaris.c          |    6 +-
 hw/sun4c_intctl.c       |    8 +-
 hw/sun4m.c              |   14 +-
 hw/sun4u.c              |   12 +-
 hw/syborg_interrupt.c   |    8 +-
 hw/tc6393xb.c           |    7 +-
 hw/tosa.c               |    2 +-
 hw/tusb6010.c           |    3 +-
 hw/twl92230.c           |    5 +-
 hw/versatilepb.c        |   10 +-
 hw/xilinx_intc.c        |    8 +-
 hw/zaurus.c             |    2 +-
 monitor.c               |   22 --
 qemu-monitor.hx         |   21 --
 84 files changed, 874 insertions(+), 643 deletions(-)

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 01/16] hpet: Catch out-of-bounds timer access
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 02/16] hpet: Coding style cleanups and some refactorings Jan Kiszka
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Also prevent out-of-bounds write access to the timers but don't spam the
host console if it triggers.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 8729fb2..1980906 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -294,7 +294,7 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
     if (index >= 0x100 && index <= 0x3ff) {
         uint8_t timer_id = (addr - 0x100) / 0x20;
         if (timer_id > HPET_NUM_TIMERS - 1) {
-            printf("qemu: timer id out of range\n");
+            DPRINTF("qemu: timer id out of range\n");
             return 0;
         }
         HPETTimer *timer = &s->timer[timer_id];
@@ -383,6 +383,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
         DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
         HPETTimer *timer = &s->timer[timer_id];
 
+        if (timer_id > HPET_NUM_TIMERS - 1) {
+            DPRINTF("qemu: timer id out of range\n");
+            return;
+        }
         switch ((addr - 0x100) % 0x20) {
             case HPET_TN_CFG:
                 DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 02/16] hpet: Coding style cleanups and some refactorings
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 01/16] hpet: Catch out-of-bounds timer access Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 03/16] hpet: Silence warning on write to running main counter Jan Kiszka
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

This moves the private HPET structures into the C module, simplifies
some helper functions and fixes most coding style issues (biggest chunk
was improper switch-case indention). No functional changes.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
---
 hw/hpet.c      |  413 ++++++++++++++++++++++++++++++-------------------------
 hw/hpet_emul.h |   31 +----
 2 files changed, 226 insertions(+), 218 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 1980906..2836fb0 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -37,21 +37,47 @@
 #define DPRINTF(...)
 #endif
 
+struct HPETState;
+typedef struct HPETTimer {  /* timers */
+    uint8_t tn;             /*timer number*/
+    QEMUTimer *qemu_timer;
+    struct HPETState *state;
+    /* Memory-mapped, software visible timer registers */
+    uint64_t config;        /* configuration/cap */
+    uint64_t cmp;           /* comparator */
+    uint64_t fsb;           /* FSB route, not supported now */
+    /* Hidden register state */
+    uint64_t period;        /* Last value written to comparator */
+    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
+                             * mode. Next pop will be actual timer expiration.
+                             */
+} HPETTimer;
+
+typedef struct HPETState {
+    uint64_t hpet_offset;
+    qemu_irq *irqs;
+    HPETTimer timer[HPET_NUM_TIMERS];
+
+    /* Memory-mapped, software visible registers */
+    uint64_t capability;        /* capabilities */
+    uint64_t config;            /* configuration */
+    uint64_t isr;               /* interrupt status reg */
+    uint64_t hpet_counter;      /* main counter */
+} HPETState;
+
 static HPETState *hpet_statep;
 
 uint32_t hpet_in_legacy_mode(void)
 {
-    if (hpet_statep)
-        return hpet_statep->config & HPET_CFG_LEGACY;
-    else
+    if (!hpet_statep) {
         return 0;
+    }
+    return hpet_statep->config & HPET_CFG_LEGACY;
 }
 
 static uint32_t timer_int_route(struct HPETTimer *timer)
 {
-    uint32_t route;
-    route = (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
-    return route;
+    return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
 static uint32_t hpet_enabled(void)
@@ -108,9 +134,7 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
 
 static uint64_t hpet_get_ticks(void)
 {
-    uint64_t ticks;
-    ticks = ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
-    return ticks;
+    return ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
 }
 
 /*
@@ -121,12 +145,14 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
 
     if (t->config & HPET_TN_32BIT) {
         uint32_t diff, cmp;
+
         cmp = (uint32_t)t->cmp;
         diff = cmp - (uint32_t)current;
         diff = (int32_t)diff > 0 ? diff : (uint32_t)0;
         return (uint64_t)diff;
     } else {
         uint64_t diff, cmp;
+
         cmp = t->cmp;
         diff = cmp - current;
         diff = (int64_t)diff > 0 ? diff : (uint64_t)0;
@@ -136,7 +162,6 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
 
 static void update_irq(struct HPETTimer *timer)
 {
-    qemu_irq irq;
     int route;
 
     if (timer->tn <= 1 && hpet_in_legacy_mode()) {
@@ -144,22 +169,20 @@ static void update_irq(struct HPETTimer *timer)
          * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
          * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
          */
-        if (timer->tn == 0) {
-            irq=timer->state->irqs[0];
-        } else
-            irq=timer->state->irqs[8];
+        route = (timer->tn == 0) ? 0 : 8;
     } else {
-        route=timer_int_route(timer);
-        irq=timer->state->irqs[route];
+        route = timer_int_route(timer);
     }
-    if (timer_enabled(timer) && hpet_enabled()) {
-        qemu_irq_pulse(irq);
+    if (!timer_enabled(timer) || !hpet_enabled()) {
+        return;
     }
+    qemu_irq_pulse(timer->state->irqs[route]);
 }
 
 static void hpet_pre_save(void *opaque)
 {
     HPETState *s = opaque;
+
     /* save current counter value */
     s->hpet_counter = hpet_get_ticks();
 }
@@ -212,7 +235,7 @@ static const VMStateDescription vmstate_hpet = {
  */
 static void hpet_timer(void *opaque)
 {
-    HPETTimer *t = (HPETTimer*)opaque;
+    HPETTimer *t = opaque;
     uint64_t diff;
 
     uint64_t period = t->period;
@@ -220,20 +243,22 @@ static void hpet_timer(void *opaque)
 
     if (timer_is_periodic(t) && period != 0) {
         if (t->config & HPET_TN_32BIT) {
-            while (hpet_time_after(cur_tick, t->cmp))
+            while (hpet_time_after(cur_tick, t->cmp)) {
                 t->cmp = (uint32_t)(t->cmp + t->period);
-        } else
-            while (hpet_time_after64(cur_tick, t->cmp))
+            }
+        } else {
+            while (hpet_time_after64(cur_tick, t->cmp)) {
                 t->cmp += period;
-
+            }
+        }
         diff = hpet_calculate_diff(t, cur_tick);
-        qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
-                       + (int64_t)ticks_to_ns(diff));
+        qemu_mod_timer(t->qemu_timer,
+                       qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
     } else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
         if (t->wrap_flag) {
             diff = hpet_calculate_diff(t, cur_tick);
-            qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
-                           + (int64_t)ticks_to_ns(diff));
+            qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock) +
+                           (int64_t)ticks_to_ns(diff));
             t->wrap_flag = 0;
         }
     }
@@ -260,8 +285,8 @@ static void hpet_set_timer(HPETTimer *t)
             t->wrap_flag = 1;
         }
     }
-    qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
-                   + (int64_t)ticks_to_ns(diff));
+    qemu_mod_timer(t->qemu_timer,
+                   qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
 }
 
 static void hpet_del_timer(HPETTimer *t)
@@ -285,7 +310,7 @@ static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
 
 static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
 {
-    HPETState *s = (HPETState *)opaque;
+    HPETState *s = opaque;
     uint64_t cur_tick, index;
 
     DPRINTF("qemu: Enter hpet_ram_readl at %" PRIx64 "\n", addr);
@@ -293,57 +318,60 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
     /*address range of all TN regs*/
     if (index >= 0x100 && index <= 0x3ff) {
         uint8_t timer_id = (addr - 0x100) / 0x20;
+        HPETTimer *timer = &s->timer[timer_id];
+
         if (timer_id > HPET_NUM_TIMERS - 1) {
             DPRINTF("qemu: timer id out of range\n");
             return 0;
         }
-        HPETTimer *timer = &s->timer[timer_id];
 
         switch ((addr - 0x100) % 0x20) {
-            case HPET_TN_CFG:
-                return timer->config;
-            case HPET_TN_CFG + 4: // Interrupt capabilities
-                return timer->config >> 32;
-            case HPET_TN_CMP: // comparator register
-                return timer->cmp;
-            case HPET_TN_CMP + 4:
-                return timer->cmp >> 32;
-            case HPET_TN_ROUTE:
-                return timer->fsb >> 32;
-            default:
-                DPRINTF("qemu: invalid hpet_ram_readl\n");
-                break;
+        case HPET_TN_CFG:
+            return timer->config;
+        case HPET_TN_CFG + 4: // Interrupt capabilities
+            return timer->config >> 32;
+        case HPET_TN_CMP: // comparator register
+            return timer->cmp;
+        case HPET_TN_CMP + 4:
+            return timer->cmp >> 32;
+        case HPET_TN_ROUTE:
+            return timer->fsb >> 32;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_readl\n");
+            break;
         }
     } else {
         switch (index) {
-            case HPET_ID:
-                return s->capability;
-            case HPET_PERIOD:
-                return s->capability >> 32;
-            case HPET_CFG:
-                return s->config;
-            case HPET_CFG + 4:
-                DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
-                return 0;
-            case HPET_COUNTER:
-                if (hpet_enabled())
-                    cur_tick = hpet_get_ticks();
-                else
-                    cur_tick = s->hpet_counter;
-                DPRINTF("qemu: reading counter  = %" PRIx64 "\n", cur_tick);
-                return cur_tick;
-            case HPET_COUNTER + 4:
-                if (hpet_enabled())
-                    cur_tick = hpet_get_ticks();
-                else
-                    cur_tick = s->hpet_counter;
-                DPRINTF("qemu: reading counter + 4  = %" PRIx64 "\n", cur_tick);
-                return cur_tick >> 32;
-            case HPET_STATUS:
-                return s->isr;
-            default:
-                DPRINTF("qemu: invalid hpet_ram_readl\n");
-                break;
+        case HPET_ID:
+            return s->capability;
+        case HPET_PERIOD:
+            return s->capability >> 32;
+        case HPET_CFG:
+            return s->config;
+        case HPET_CFG + 4:
+            DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
+            return 0;
+        case HPET_COUNTER:
+            if (hpet_enabled()) {
+                cur_tick = hpet_get_ticks();
+            } else {
+                cur_tick = s->hpet_counter;
+            }
+            DPRINTF("qemu: reading counter  = %" PRIx64 "\n", cur_tick);
+            return cur_tick;
+        case HPET_COUNTER + 4:
+            if (hpet_enabled()) {
+                cur_tick = hpet_get_ticks();
+            } else {
+                cur_tick = s->hpet_counter;
+            }
+            DPRINTF("qemu: reading counter + 4  = %" PRIx64 "\n", cur_tick);
+            return cur_tick >> 32;
+        case HPET_STATUS:
+            return s->isr;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_readl\n");
+            break;
         }
     }
     return 0;
@@ -369,7 +397,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                             uint32_t value)
 {
     int i;
-    HPETState *s = (HPETState *)opaque;
+    HPETState *s = opaque;
     uint64_t old_val, new_val, val, index;
 
     DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
@@ -380,133 +408,137 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
     /*address range of all TN regs*/
     if (index >= 0x100 && index <= 0x3ff) {
         uint8_t timer_id = (addr - 0x100) / 0x20;
-        DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
         HPETTimer *timer = &s->timer[timer_id];
 
+        DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
         if (timer_id > HPET_NUM_TIMERS - 1) {
             DPRINTF("qemu: timer id out of range\n");
             return;
         }
         switch ((addr - 0x100) % 0x20) {
-            case HPET_TN_CFG:
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
-                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;
-                }
-                if (new_val & HPET_TIMER_TYPE_LEVEL) {
-                    printf("qemu: level-triggered hpet not supported\n");
-                    exit (-1);
-                }
-
-                break;
-            case HPET_TN_CFG + 4: // Interrupt capabilities
-                DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
-                break;
-            case HPET_TN_CMP: // comparator register
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP \n");
-                if (timer->config & HPET_TN_32BIT)
-                    new_val = (uint32_t)new_val;
-                if (!timer_is_periodic(timer) ||
-                           (timer->config & HPET_TN_SETVAL))
-                    timer->cmp = (timer->cmp & 0xffffffff00000000ULL)
-                                  | new_val;
-                if (timer_is_periodic(timer)) {
-                    /*
-                     * FIXME: Clamp period to reasonable min value?
-                     * Clamp period to reasonable max value
-                     */
-                    new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
-                    timer->period = (timer->period & 0xffffffff00000000ULL)
-                                     | new_val;
+        case HPET_TN_CFG:
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
+            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;
+            }
+            if (new_val & HPET_TN_TYPE_LEVEL) {
+                printf("qemu: level-triggered hpet not supported\n");
+                exit (-1);
+            }
+            break;
+        case HPET_TN_CFG + 4: // Interrupt capabilities
+            DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
+            break;
+        case HPET_TN_CMP: // comparator register
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP \n");
+            if (timer->config & HPET_TN_32BIT) {
+                new_val = (uint32_t)new_val;
+            }
+            if (!timer_is_periodic(timer)
+                || (timer->config & HPET_TN_SETVAL)) {
+                timer->cmp = (timer->cmp & 0xffffffff00000000ULL) | new_val;
+            }
+            if (timer_is_periodic(timer)) {
+                /*
+                 * FIXME: Clamp period to reasonable min value?
+                 * Clamp period to reasonable max value
+                 */
+                new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
+                timer->period =
+                    (timer->period & 0xffffffff00000000ULL) | new_val;
+            }
+            timer->config &= ~HPET_TN_SETVAL;
+            if (hpet_enabled()) {
+                hpet_set_timer(timer);
+            }
+            break;
+        case HPET_TN_CMP + 4: // comparator register high order
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
+            if (!timer_is_periodic(timer)
+                || (timer->config & HPET_TN_SETVAL)) {
+                timer->cmp = (timer->cmp & 0xffffffffULL) | new_val << 32;
+            } else {
+                /*
+                 * FIXME: Clamp period to reasonable min value?
+                 * Clamp period to reasonable max value
+                 */
+                new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
+                timer->period =
+                    (timer->period & 0xffffffffULL) | new_val << 32;
                 }
                 timer->config &= ~HPET_TN_SETVAL;
-                if (hpet_enabled())
+                if (hpet_enabled()) {
                     hpet_set_timer(timer);
-                break;
-            case HPET_TN_CMP + 4: // comparator register high order
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
-                if (!timer_is_periodic(timer) ||
-                           (timer->config & HPET_TN_SETVAL))
-                    timer->cmp = (timer->cmp & 0xffffffffULL)
-                                  | new_val << 32;
-                else {
-                    /*
-                     * FIXME: Clamp period to reasonable min value?
-                     * Clamp period to reasonable max value
-                     */
-                    new_val &= (timer->config
-                                & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
-                    timer->period = (timer->period & 0xffffffffULL)
-                                     | new_val << 32;
                 }
-                timer->config &= ~HPET_TN_SETVAL;
-                if (hpet_enabled())
-                    hpet_set_timer(timer);
-                break;
-            case HPET_TN_ROUTE + 4:
-                DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
-                break;
-            default:
-                DPRINTF("qemu: invalid hpet_ram_writel\n");
                 break;
+        case HPET_TN_ROUTE + 4:
+            DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+            break;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_writel\n");
+            break;
         }
         return;
     } else {
         switch (index) {
-            case HPET_ID:
-                return;
-            case HPET_CFG:
-                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)
-                                     - qemu_get_clock(vm_clock);
-                    for (i = 0; i < HPET_NUM_TIMERS; i++)
-                        if ((&s->timer[i])->cmp != ~0ULL)
-                            hpet_set_timer(&s->timer[i]);
-                }
-                else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
-                    /* Halt main counter and disable interrupt generation. */
-                    s->hpet_counter = hpet_get_ticks();
-                    for (i = 0; i < HPET_NUM_TIMERS; i++)
-                        hpet_del_timer(&s->timer[i]);
+        case HPET_ID:
+            return;
+        case HPET_CFG:
+            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) - qemu_get_clock(vm_clock);
+                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                    if ((&s->timer[i])->cmp != ~0ULL) {
+                        hpet_set_timer(&s->timer[i]);
+                    }
                 }
-                /* i8254 and RTC are disabled when HPET is in legacy mode */
-                if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
-                    hpet_pit_disable();
-                } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
-                    hpet_pit_enable();
+            } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+                /* Halt main counter and disable interrupt generation. */
+                s->hpet_counter = hpet_get_ticks();
+                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                    hpet_del_timer(&s->timer[i]);
                 }
-                break;
-            case HPET_CFG + 4:
-                DPRINTF("qemu: invalid HPET_CFG+4 write \n");
-                break;
-            case HPET_STATUS:
-                /* FIXME: need to handle level-triggered interrupts */
-                break;
-            case HPET_COUNTER:
-               if (hpet_enabled())
-                   printf("qemu: Writing counter while HPET enabled!\n");
-               s->hpet_counter = (s->hpet_counter & 0xffffffff00000000ULL)
-                                  | value;
-               DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
-                        value, s->hpet_counter);
-               break;
-            case HPET_COUNTER + 4:
-               if (hpet_enabled())
-                   printf("qemu: Writing counter while HPET enabled!\n");
-               s->hpet_counter = (s->hpet_counter & 0xffffffffULL)
-                                  | (((uint64_t)value) << 32);
-               DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
-                        value, s->hpet_counter);
-               break;
-            default:
-               DPRINTF("qemu: invalid hpet_ram_writel\n");
-               break;
+            }
+            /* i8254 and RTC are disabled when HPET is in legacy mode */
+            if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+                hpet_pit_disable();
+            } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+                hpet_pit_enable();
+            }
+            break;
+        case HPET_CFG + 4:
+            DPRINTF("qemu: invalid HPET_CFG+4 write \n");
+            break;
+        case HPET_STATUS:
+            /* FIXME: need to handle level-triggered interrupts */
+            break;
+        case HPET_COUNTER:
+            if (hpet_enabled()) {
+                printf("qemu: Writing counter while HPET enabled!\n");
+            }
+            s->hpet_counter =
+                (s->hpet_counter & 0xffffffff00000000ULL) | value;
+            DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
+                    value, s->hpet_counter);
+            break;
+        case HPET_COUNTER + 4:
+            if (hpet_enabled()) {
+                printf("qemu: Writing counter while HPET enabled!\n");
+            }
+            s->hpet_counter =
+                (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
+            DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
+                    value, s->hpet_counter);
+            break;
+        default:
+            DPRINTF("qemu: invalid hpet_ram_writel\n");
+            break;
         }
     }
 }
@@ -533,13 +565,15 @@ static CPUWriteMemoryFunc * const hpet_ram_write[] = {
     hpet_ram_writel,
 };
 
-static void hpet_reset(void *opaque) {
+static void hpet_reset(void *opaque)
+{
     HPETState *s = opaque;
     int i;
     static int count = 0;
 
-    for (i=0; i<HPET_NUM_TIMERS; i++) {
+    for (i = 0; i < HPET_NUM_TIMERS; i++) {
         HPETTimer *timer = &s->timer[i];
+
         hpet_del_timer(timer);
         timer->tn = i;
         timer->cmp = ~0ULL;
@@ -557,19 +591,22 @@ static void hpet_reset(void *opaque) {
     s->capability = 0x8086a201ULL;
     s->capability |= ((HPET_CLK_PERIOD) << 32);
     s->config = 0ULL;
-    if (count > 0)
+    if (count > 0) {
         /* we don't enable pit when hpet_reset is first called (by hpet_init)
          * because hpet is taking over for pit here. On subsequent invocations,
          * hpet_reset is called due to system reset. At this point control must
          * be returned to pit until SW reenables hpet.
          */
         hpet_pit_enable();
+    }
     count = 1;
 }
 
 
-void hpet_init(qemu_irq *irq) {
+void hpet_init(qemu_irq *irq)
+{
     int i, iomemtype;
+    HPETTimer *timer;
     HPETState *s;
 
     DPRINTF ("hpet_init\n");
@@ -577,8 +614,8 @@ void hpet_init(qemu_irq *irq) {
     s = qemu_mallocz(sizeof(HPETState));
     hpet_statep = s;
     s->irqs = irq;
-    for (i=0; i<HPET_NUM_TIMERS; i++) {
-        HPETTimer *timer = &s->timer[i];
+    for (i = 0; i < HPET_NUM_TIMERS; i++) {
+        timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
     }
     vmstate_register(-1, &vmstate_hpet, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index cfd95b4..2f5f8ba 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -18,7 +18,6 @@
 
 #define FS_PER_NS 1000000
 #define HPET_NUM_TIMERS 3
-#define HPET_TIMER_TYPE_LEVEL 0x002
 
 #define HPET_CFG_ENABLE 0x001
 #define HPET_CFG_LEGACY 0x002
@@ -33,7 +32,7 @@
 #define HPET_TN_ROUTE   0x010
 #define HPET_CFG_WRITE_MASK  0x3
 
-
+#define HPET_TN_TYPE_LEVEL       0x002
 #define HPET_TN_ENABLE           0x004
 #define HPET_TN_PERIODIC         0x008
 #define HPET_TN_PERIODIC_CAP     0x010
@@ -46,34 +45,6 @@
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
 
-struct HPETState;
-typedef struct HPETTimer {  /* timers */
-    uint8_t tn;             /*timer number*/
-    QEMUTimer *qemu_timer;
-    struct HPETState *state;
-    /* Memory-mapped, software visible timer registers */
-    uint64_t config;        /* configuration/cap */
-    uint64_t cmp;           /* comparator */
-    uint64_t fsb;           /* FSB route, not supported now */
-    /* Hidden register state */
-    uint64_t period;        /* Last value written to comparator */
-    uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
-                             * mode. Next pop will be actual timer expiration.
-                             */
-} HPETTimer;
-
-typedef struct HPETState {
-    uint64_t hpet_offset;
-    qemu_irq *irqs;
-    HPETTimer timer[HPET_NUM_TIMERS];
-
-    /* Memory-mapped, software visible registers */
-    uint64_t capability;        /* capabilities */
-    uint64_t config;            /* configuration */
-    uint64_t isr;               /* interrupt status reg */
-    uint64_t hpet_counter;      /* main counter */
-} HPETState;
-
 #if defined TARGET_I386
 extern uint32_t hpet_in_legacy_mode(void);
 extern void hpet_init(qemu_irq *irq);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 03/16] hpet: Silence warning on write to running main counter
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 01/16] hpet: Catch out-of-bounds timer access Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 02/16] hpet: Coding style cleanups and some refactorings Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 04/16] hpet: Move static timer field initialization Jan Kiszka
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Setting the main counter while the HPET is enabled may not be a good
idea of the guest, but it is supported and should, thus, not spam the
host console with warnings.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 2836fb0..bcb160b 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -520,7 +520,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             break;
         case HPET_COUNTER:
             if (hpet_enabled()) {
-                printf("qemu: Writing counter while HPET enabled!\n");
+                DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
                 (s->hpet_counter & 0xffffffff00000000ULL) | value;
@@ -529,7 +529,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             break;
         case HPET_COUNTER + 4:
             if (hpet_enabled()) {
-                printf("qemu: Writing counter while HPET enabled!\n");
+                DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
                 (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 04/16] hpet: Move static timer field initialization
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (2 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 03/16] hpet: Silence warning on write to running main counter Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 05/16] hpet: Convert to qdev Jan Kiszka
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Properly initialize HPETTimer::tn and HPETTimer::state once during
hpet_init instead of (re-)writing them on every reset.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index bcb160b..fd7a1fd 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -575,12 +575,10 @@ static void hpet_reset(void *opaque)
         HPETTimer *timer = &s->timer[i];
 
         hpet_del_timer(timer);
-        timer->tn = i;
         timer->cmp = ~0ULL;
         timer->config =  HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
         /* advertise availability of ioapic inti2 */
         timer->config |=  0x00000004ULL << 32;
-        timer->state = s;
         timer->period = 0ULL;
         timer->wrap_flag = 0;
     }
@@ -617,6 +615,8 @@ void hpet_init(qemu_irq *irq)
     for (i = 0; i < HPET_NUM_TIMERS; i++) {
         timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
+        timer->tn = i;
+        timer->state = s;
     }
     vmstate_register(-1, &vmstate_hpet, s);
     qemu_register_reset(hpet_reset, s);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 05/16] hpet: Convert to qdev
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (3 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 04/16] hpet: Move static timer field initialization Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 06/16] hpet: Start/stop timer when HPET_TN_ENABLE is modified Jan Kiszka
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Register the HPET as a sysbus device and create it that way. As it can
route its IRQs to any ISA IRQ, we need to connect it to all 24 of them.
Once converted to qdev, we can move reset handler and vmstate
registration into its hands as well.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c      |   43 ++++++++++++++++++++++++++++++-------------
 hw/hpet_emul.h |    3 ++-
 hw/pc.c        |    7 ++++++-
 3 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index fd7a1fd..6974935 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -29,6 +29,7 @@
 #include "console.h"
 #include "qemu-timer.h"
 #include "hpet_emul.h"
+#include "sysbus.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -54,8 +55,9 @@ typedef struct HPETTimer {  /* timers */
 } HPETTimer;
 
 typedef struct HPETState {
+    SysBusDevice busdev;
     uint64_t hpet_offset;
-    qemu_irq *irqs;
+    qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     HPETTimer timer[HPET_NUM_TIMERS];
 
     /* Memory-mapped, software visible registers */
@@ -565,9 +567,9 @@ static CPUWriteMemoryFunc * const hpet_ram_write[] = {
     hpet_ram_writel,
 };
 
-static void hpet_reset(void *opaque)
+static void hpet_reset(DeviceState *d)
 {
-    HPETState *s = opaque;
+    HPETState *s = FROM_SYSBUS(HPETState, sysbus_from_qdev(d));
     int i;
     static int count = 0;
 
@@ -600,28 +602,43 @@ static void hpet_reset(void *opaque)
     count = 1;
 }
 
-
-void hpet_init(qemu_irq *irq)
+static int hpet_init(SysBusDevice *dev)
 {
+    HPETState *s = FROM_SYSBUS(HPETState, dev);
     int i, iomemtype;
     HPETTimer *timer;
-    HPETState *s;
-
-    DPRINTF ("hpet_init\n");
 
-    s = qemu_mallocz(sizeof(HPETState));
+    assert(!hpet_statep);
     hpet_statep = s;
-    s->irqs = irq;
+    for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
+        sysbus_init_irq(dev, &s->irqs[i]);
+    }
     for (i = 0; i < HPET_NUM_TIMERS; i++) {
         timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
         timer->tn = i;
         timer->state = s;
     }
-    vmstate_register(-1, &vmstate_hpet, s);
-    qemu_register_reset(hpet_reset, s);
+
     /* HPET Area */
     iomemtype = cpu_register_io_memory(hpet_ram_read,
                                        hpet_ram_write, s);
-    cpu_register_physical_memory(HPET_BASE, 0x400, iomemtype);
+    sysbus_init_mmio(dev, 0x400, iomemtype);
+    return 0;
 }
+
+static SysBusDeviceInfo hpet_device_info = {
+    .qdev.name    = "hpet",
+    .qdev.size    = sizeof(HPETState),
+    .qdev.no_user = 1,
+    .qdev.vmsd    = &vmstate_hpet,
+    .qdev.reset   = hpet_reset,
+    .init         = hpet_init,
+};
+
+static void hpet_register_device(void)
+{
+    sysbus_register_withprop(&hpet_device_info);
+}
+
+device_init(hpet_register_device)
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 2f5f8ba..785f850 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -19,6 +19,8 @@
 #define FS_PER_NS 1000000
 #define HPET_NUM_TIMERS 3
 
+#define HPET_NUM_IRQ_ROUTES     32
+
 #define HPET_CFG_ENABLE 0x001
 #define HPET_CFG_LEGACY 0x002
 
@@ -47,7 +49,6 @@
 
 #if defined TARGET_I386
 extern uint32_t hpet_in_legacy_mode(void);
-extern void hpet_init(qemu_irq *irq);
 #endif
 
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 9b85c42..ae31e2e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -35,6 +35,7 @@
 #include "elf.h"
 #include "multiboot.h"
 #include "mc146818rtc.h"
+#include "sysbus.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -957,7 +958,11 @@ void pc_basic_device_init(qemu_irq *isa_irq,
     pit = pit_init(0x40, isa_reserve_irq(0));
     pcspk_init(pit);
     if (!no_hpet) {
-        hpet_init(isa_irq);
+        DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
+
+        for (i = 0; i < 24; i++) {
+            sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
+        }
     }
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 06/16] hpet: Start/stop timer when HPET_TN_ENABLE is modified
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (4 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 05/16] hpet: Convert to qdev Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 07/16] monitor/QMP: Drop info hpet / query-hpet Jan Kiszka
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

We have to update the qemu timer when the per-timer enable bit is
toggled, just like for HPET_CFG_ENABLE changes.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 6974935..041dd84 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -430,6 +430,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 printf("qemu: level-triggered hpet not supported\n");
                 exit (-1);
             }
+            if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+                hpet_set_timer(timer);
+            } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+                hpet_del_timer(timer);
+            }
             break;
         case HPET_TN_CFG + 4: // Interrupt capabilities
             DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 07/16] monitor/QMP: Drop info hpet / query-hpet
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (5 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 06/16] hpet: Start/stop timer when HPET_TN_ENABLE is modified Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 08/16] Pass IRQ object on handler invocation Jan Kiszka
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

This command was of minimal use before, now it is useless as the hpet
become a qdev device and is thus easily discoverable. We should
definitely not set query-hpet in QMP's stone, and there is also no good
reason to keep it for the interactive monitor.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 QMP/vm-info     |    2 +-
 monitor.c       |   22 ----------------------
 qemu-monitor.hx |   21 ---------------------
 3 files changed, 1 insertions(+), 44 deletions(-)

diff --git a/QMP/vm-info b/QMP/vm-info
index b150d82..8ebaeb3 100755
--- a/QMP/vm-info
+++ b/QMP/vm-info
@@ -25,7 +25,7 @@ def main():
     qemu = qmp.QEMUMonitorProtocol(argv[1])
     qemu.connect()
 
-    for cmd in [ 'version', 'hpet', 'kvm', 'status', 'uuid', 'balloon' ]:
+    for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]:
         print cmd + ': ' + str(qemu.send('query-' + cmd))
 
 if __name__ == '__main__':
diff --git a/monitor.c b/monitor.c
index 15b53b9..14f77bd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -740,20 +740,6 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
     *ret_data = QOBJECT(cmd_list);
 }
 
-#if defined(TARGET_I386)
-static void do_info_hpet_print(Monitor *mon, const QObject *data)
-{
-    monitor_printf(mon, "HPET is %s by QEMU\n",
-                   qdict_get_bool(qobject_to_qdict(data), "enabled") ?
-                   "enabled" : "disabled");
-}
-
-static void do_info_hpet(Monitor *mon, QObject **ret_data)
-{
-    *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
-}
-#endif
-
 static void do_info_uuid_print(Monitor *mon, const QObject *data)
 {
     monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
@@ -2509,14 +2495,6 @@ static const mon_cmd_t info_cmds[] = {
         .help       = "show the active virtual memory mappings",
         .mhandler.info = mem_info,
     },
-    {
-        .name       = "hpet",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show state of HPET",
-        .user_print = do_info_hpet_print,
-        .mhandler.info_new = do_info_hpet,
-    },
 #endif
     {
         .name       = "jit",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index f6a94f2..9f62b94 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -2144,27 +2144,6 @@ show the active virtual memory mappings (i386 only)
 ETEXI
 
 STEXI
-@item info hpet
-show state of HPET (i386 only)
-ETEXI
-SQMP
-query-hpet
-----------
-
-Show HPET state.
-
-Return a json-object with the following information:
-
-- "enabled": true if hpet if enabled, false otherwise (json-bool)
-
-Example:
-
--> { "execute": "query-hpet" }
-<- { "return": { "enabled": true } }
-
-EQMP
-
-STEXI
 @item info jit
 show dynamic compiler info
 @item info kvm
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 08/16] Pass IRQ object on handler invocation
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (6 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 07/16] monitor/QMP: Drop info hpet / query-hpet Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-12 10:31   ` [Qemu-devel] [PATCH v3 " Jan Kiszka
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs Jan Kiszka
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Pass the qemu_irq object to its handler when delivering an event. This
enables the handler to invoke optional services that require an object
reference. Will be used for IRQs with attached messages.

There are a few direct handler calls. So far we simply pass NULL as IRQ
object. Once those handlers want to make use of the object, the direct
callers need to obtain and forward a proper reference.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/acpi_piix4.c         |    3 ++-
 hw/apic.h               |    1 -
 hw/arm11mpcore.c        |   12 ++++++------
 hw/arm_gic.c            |   18 +++++++++---------
 hw/arm_pic.c            |    6 +++---
 hw/arm_timer.c          |    4 ++--
 hw/bitbang_i2c.c        |    4 ++--
 hw/bt-hci-csr.c         |    2 +-
 hw/cbus.c               |    6 +++---
 hw/cris_pic_cpu.c       |    4 ++--
 hw/esp.c                |    2 +-
 hw/etraxfs_pic.c        |   16 ++++++++--------
 hw/fdc.c                |    2 +-
 hw/heathrow_pic.c       |    3 ++-
 hw/i8259.c              |   14 +++++++-------
 hw/ide/cmd646.c         |    2 +-
 hw/ide/microdrive.c     |    2 +-
 hw/integratorcp.c       |   10 +++++-----
 hw/ioapic.c             |    2 +-
 hw/irq.c                |   13 ++++++-------
 hw/irq.h                |    4 +---
 hw/lance.c              |    2 +-
 hw/max7310.c            |    2 +-
 hw/mcf5206.c            |    6 +++---
 hw/mcf_intc.c           |   14 ++++++++------
 hw/microblaze_pic_cpu.c |    5 +++--
 hw/mips_int.c           |   10 +++++-----
 hw/mips_jazz.c          |    2 +-
 hw/mips_malta.c         |    2 +-
 hw/mst_fpga.c           |   10 +++++-----
 hw/musicpal.c           |   16 +++++++++-------
 hw/nseries.c            |    4 ++--
 hw/omap.h               |    2 +-
 hw/omap1.c              |   34 ++++++++++++++++++----------------
 hw/omap2.c              |    8 +++++---
 hw/omap_dma.c           |    8 ++++----
 hw/omap_mmc.c           |    2 +-
 hw/openpic.c            |    6 +++---
 hw/palm.c               |    2 +-
 hw/pc.c                 |   15 ++++++++-------
 hw/pc.h                 |    8 +++-----
 hw/pci.c                |    4 ++--
 hw/pl061.c              |    4 ++--
 hw/pl190.c              |    6 +++---
 hw/ppc.c                |    8 ++++----
 hw/ppc4xx_devs.c        |    2 +-
 hw/ppc_prep.c           |    2 +-
 hw/pxa2xx.c             |    2 +-
 hw/pxa2xx_gpio.c        |    2 +-
 hw/pxa2xx_pcmcia.c      |    3 ++-
 hw/pxa2xx_pic.c         |   10 +++++-----
 hw/r2d.c                |    2 +-
 hw/rc4030.c             |    7 ++++---
 hw/sbi.c                |    2 +-
 hw/sh_intc.c            |    4 ++--
 hw/sh_intc.h            |    2 +-
 hw/sharpsl.h            |    1 -
 hw/slavio_intctl.c      |   16 ++++++++--------
 hw/slavio_misc.c        |    3 ++-
 hw/sparc32_dma.c        |    2 +-
 hw/spitz.c              |   14 ++++++++------
 hw/ssd0323.c            |    2 +-
 hw/stellaris.c          |    6 ++++--
 hw/sun4c_intctl.c       |    8 ++++----
 hw/sun4m.c              |   14 +++++++-------
 hw/sun4u.c              |   12 ++++++------
 hw/syborg_interrupt.c   |    8 ++++----
 hw/tc6393xb.c           |    7 ++++---
 hw/tosa.c               |    2 +-
 hw/tusb6010.c           |    3 ++-
 hw/twl92230.c           |    5 +++--
 hw/versatilepb.c        |   10 +++++-----
 hw/xilinx_intc.c        |    8 ++++----
 hw/zaurus.c             |    2 +-
 74 files changed, 243 insertions(+), 228 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0fce958..a2268b2 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -316,7 +316,8 @@ static void piix4_reset(void *opaque)
     }
 }
 
-static void piix4_powerdown(void *opaque, int irq, int power_failing)
+static void piix4_powerdown(qemu_irq irq, void *opaque, int n,
+                            int power_failing)
 {
     PIIX4PMState *s = opaque;
 
diff --git a/hw/apic.h b/hw/apic.h
index 132fcab..e1954f4 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -11,7 +11,6 @@ int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
-void ioapic_set_irq(void *opaque, int vector, int level);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 3bbd885..694e238 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -32,18 +32,18 @@ static const int mpcore_irq_map[32] = {
     -1, -1, -1, -1,  9,  3, -1, -1,
 };
 
-static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
+static void mpcore_rirq_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
     int i;
 
     for (i = 0; i < 4; i++) {
-        qemu_set_irq(s->rvic[i][irq], level);
+        qemu_set_irq(s->rvic[i][n], level);
     }
-    if (irq < 32) {
-        irq = mpcore_irq_map[irq];
-        if (irq >= 0) {
-            qemu_set_irq(s->cpuic[irq], level);
+    if (n < 32) {
+        n = mpcore_irq_map[n];
+        if (n >= 0) {
+            qemu_set_irq(s->cpuic[n], level);
         }
     }
 }
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index c4afc6a..90aeb09 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -161,22 +161,22 @@ gic_set_pending_private(gic_state *s, int cpu, int irq)
 }
 
 /* Process a change in an external IRQ input.  */
-static void gic_set_irq(void *opaque, int irq, int level)
+static void gic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     gic_state *s = (gic_state *)opaque;
     /* The first external input line is internal interrupt 32.  */
-    irq += 32;
-    if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
+    n += 32;
+    if (level == GIC_TEST_LEVEL(n, ALL_CPU_MASK)) {
         return;
-
+    }
     if (level) {
-        GIC_SET_LEVEL(irq, ALL_CPU_MASK);
-        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
-            DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
-            GIC_SET_PENDING(irq, GIC_TARGET(irq));
+        GIC_SET_LEVEL(n, ALL_CPU_MASK);
+        if (GIC_TEST_TRIGGER(n) || GIC_TEST_ENABLED(n)) {
+            DPRINTF("Set %d pending mask %x\n", n, GIC_TARGET(n));
+            GIC_SET_PENDING(n, GIC_TARGET(n));
         }
     } else {
-        GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
+        GIC_CLEAR_LEVEL(n, ALL_CPU_MASK);
     }
     gic_update(s);
 }
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index f44568c..d6f8acc 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -22,10 +22,10 @@ void irq_info(Monitor *mon)
 
 
 /* Input 0 is IRQ and input 1 is FIQ.  */
-static void arm_pic_cpu_handler(void *opaque, int irq, int level)
+static void arm_pic_cpu_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = (CPUState *)opaque;
-    switch (irq) {
+    switch (n) {
     case ARM_PIC_CPU_IRQ:
         if (level)
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -39,7 +39,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
             cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
         break;
     default:
-        hw_error("arm_pic_cpu_handler: Bad interrput line %d\n", irq);
+        hw_error("arm_pic_cpu_handler: Bad interrput line %d\n", n);
     }
 }
 
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9073ffc..074254a 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -191,11 +191,11 @@ typedef struct {
 } sp804_state;
 
 /* Merge the IRQs from the two component devices.  */
-static void sp804_set_irq(void *opaque, int irq, int level)
+static void sp804_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     sp804_state *s = (sp804_state *)opaque;
 
-    s->level[irq] = level;
+    s->level[n] = level;
     qemu_set_irq(s->irq, s->level[0] || s->level[1]);
 }
 
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 4ee99a1..d4708d2 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -186,11 +186,11 @@ typedef struct {
     qemu_irq out;
 } GPIOI2CState;
 
-static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
+static void bitbang_i2c_gpio_set(qemu_irq irq, void *opaque, int n, int level)
 {
     GPIOI2CState *s = opaque;
 
-    level = bitbang_i2c_set(s->bitbang, irq, level);
+    level = bitbang_i2c_set(s->bitbang, n, level);
     if (level != s->last_level) {
         s->last_level = level;
         qemu_set_irq(s->out, level);
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 982577d..1d63a5d 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -406,7 +406,7 @@ static void csrhci_out_tick(void *opaque)
     csrhci_fifo_wake((struct csrhci_s *) opaque);
 }
 
-static void csrhci_pins(void *opaque, int line, int level)
+static void csrhci_pins(qemu_irq irq, void *opaque, int line, int level)
 {
     struct csrhci_s *s = (struct csrhci_s *) opaque;
     int state = s->pin_state;
diff --git a/hw/cbus.c b/hw/cbus.c
index 8ae24e0..fa01ec0 100644
--- a/hw/cbus.c
+++ b/hw/cbus.c
@@ -93,7 +93,7 @@ static void cbus_cycle(CBusPriv *s)
     }
 }
 
-static void cbus_clk(void *opaque, int line, int level)
+static void cbus_clk(qemu_irq irq, void *opaque, int line, int level)
 {
     CBusPriv *s = (CBusPriv *) opaque;
 
@@ -110,14 +110,14 @@ static void cbus_clk(void *opaque, int line, int level)
     s->clk = level;
 }
 
-static void cbus_dat(void *opaque, int line, int level)
+static void cbus_dat(qemu_irq irq, void *opaque, int line, int level)
 {
     CBusPriv *s = (CBusPriv *) opaque;
 
     s->dat = level;
 }
 
-static void cbus_sel(void *opaque, int line, int level)
+static void cbus_sel(qemu_irq irq, void *opaque, int line, int level)
 {
     CBusPriv *s = (CBusPriv *) opaque;
 
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index a92d445..f85ac24 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -33,10 +33,10 @@ void pic_info(Monitor *mon)
 void irq_info(Monitor *mon)
 {}
 
-static void cris_pic_cpu_handler(void *opaque, int irq, int level)
+static void cris_pic_cpu_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = (CPUState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+    int type = n ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level)
         cpu_interrupt(env, type);
diff --git a/hw/esp.c b/hw/esp.c
index 0a8cf6e..a657eba 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -435,7 +435,7 @@ static void esp_reset(DeviceState *d)
     s->rregs[ESP_CFG1] = 7;
 }
 
-static void parent_esp_reset(void *opaque, int irq, int level)
+static void parent_esp_reset(qemu_irq irq, void *opaque, int n, int level)
 {
     if (level)
         esp_reset(opaque);
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index b2c4859..c612316 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -123,16 +123,16 @@ static void nmi_handler(void *opaque, int irq, int level)
     qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
 }
 
-static void irq_handler(void *opaque, int irq, int level)
-{   
+static void irq_handler(qemu_irq irq, void *opaque, int n, int level)
+{
     struct etrax_pic *fs = (void *)opaque;
 
-    if (irq >= 30)
-        return nmi_handler(opaque, irq, level);
-
-    irq -= 1;
-    fs->regs[R_R_VECT] &= ~(1 << irq);
-    fs->regs[R_R_VECT] |= (!!level << irq);
+    if (n >= 30) {
+        return nmi_handler(opaque, n, level);
+    }
+    n -= 1;
+    fs->regs[R_R_VECT] &= ~(1 << n);
+    fs->regs[R_R_VECT] |= (!!level << n);
     pic_update(fs);
 }
 
diff --git a/hw/fdc.c b/hw/fdc.c
index 6306496..d884d33 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -716,7 +716,7 @@ static void fdctrl_external_reset_isa(DeviceState *d)
     fdctrl_reset(s, 0);
 }
 
-static void fdctrl_handle_tc(void *opaque, int irq, int level)
+static void fdctrl_handle_tc(qemu_irq irq, void *opaque, int n, int level)
 {
     //FDCtrl *s = opaque;
 
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index 5e27021..1492312 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -135,7 +135,8 @@ static CPUReadMemoryFunc * const pic_read[] = {
 };
 
 
-static void heathrow_pic_set_irq(void *opaque, int num, int level)
+static void heathrow_pic_set_irq(qemu_irq irq, void *opaque, int num,
+                                 int level)
 {
     HeathrowPICS *s = opaque;
     HeathrowPIC *pic;
diff --git a/hw/i8259.c b/hw/i8259.c
index a995280..f743ee8 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -186,26 +186,26 @@ void pic_update_irq(PicState2 *s)
 int64_t irq_time[16];
 #endif
 
-static void i8259_set_irq(void *opaque, int irq, int level)
+static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     PicState2 *s = opaque;
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
-    if (level != irq_level[irq]) {
-        DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level);
-        irq_level[irq] = level;
+    if (level != irq_level[n]) {
+        DPRINTF("i8259_set_irq: irq=%d level=%d\n", n, level);
+        irq_level[n] = level;
 #ifdef DEBUG_IRQ_COUNT
 	if (level == 1)
-	    irq_count[irq]++;
+	    irq_count[n]++;
 #endif
     }
 #endif
 #ifdef DEBUG_IRQ_LATENCY
     if (level) {
-        irq_time[irq] = qemu_get_clock(vm_clock);
+        irq_time[n] = qemu_get_clock(vm_clock);
     }
 #endif
-    pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
+    pic_set_irq1(&s->pics[n >> 3], n & 7, level);
     pic_update_irq(s);
 }
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index cdcc9bf..8ca55ea 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -202,7 +202,7 @@ static void cmd646_update_irq(PCIIDEState *d)
 }
 
 /* the PCI irq level is the logical OR of the two channels */
-static void cmd646_set_irq(void *opaque, int channel, int level)
+static void cmd646_set_irq(qemu_irq irq, void *opaque, int channel, int level)
 {
     PCIIDEState *d = opaque;
     int irq_mask;
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index bfdb8c8..c852665 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -92,7 +92,7 @@ static inline void md_interrupt_update(MicroDriveState *s)
                     !(s->opt & OPT_SRESET));
 }
 
-static void md_set_irq(void *opaque, int irq, int level)
+static void md_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     MicroDriveState *s = opaque;
     if (level)
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index bee8298..db78f04 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -286,13 +286,13 @@ static void icp_pic_update(icp_pic_state *s)
     qemu_set_irq(s->parent_fiq, flags != 0);
 }
 
-static void icp_pic_set_irq(void *opaque, int irq, int level)
+static void icp_pic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     icp_pic_state *s = (icp_pic_state *)opaque;
     if (level)
-        s->level |= 1 << irq;
+        s->level |= 1 << n;
     else
-        s->level &= ~(1 << irq);
+        s->level &= ~(1 << n);
     icp_pic_update(s);
 }
 
@@ -338,11 +338,11 @@ static void icp_pic_write(void *opaque, target_phys_addr_t offset,
         break;
     case 4: /* INT_SOFTSET */
         if (value & 1)
-            icp_pic_set_irq(s, 0, 1);
+            icp_pic_set_irq(NULL, s, 0, 1);
         break;
     case 5: /* INT_SOFTCLR */
         if (value & 1)
-            icp_pic_set_irq(s, 0, 0);
+            icp_pic_set_irq(NULL, s, 0, 0);
         break;
     case 10: /* FRQ_ENABLESET */
         s->fiq_enabled |= value;
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 335da6e..d818573 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -94,7 +94,7 @@ static void ioapic_service(IOAPICState *s)
     }
 }
 
-void ioapic_set_irq(void *opaque, int vector, int level)
+static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
 {
     IOAPICState *s = opaque;
 
diff --git a/hw/irq.c b/hw/irq.c
index 7703f62..24fb09d 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -32,10 +32,9 @@ struct IRQState {
 
 void qemu_set_irq(qemu_irq irq, int level)
 {
-    if (!irq)
-        return;
-
-    irq->handler(irq->opaque, irq->n, level);
+    if (irq) {
+        irq->handler(irq, irq->opaque, irq->n, level);
+    }
 }
 
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
@@ -62,11 +61,11 @@ void qemu_free_irqs(qemu_irq *s)
     qemu_free(s);
 }
 
-static void qemu_notirq(void *opaque, int line, int level)
+static void qemu_notirq(qemu_irq irq, void *opaque, int line, int level)
 {
-    struct IRQState *irq = opaque;
+    struct IRQState *inv_irq = opaque;
 
-    irq->handler(irq->opaque, irq->n, !level);
+    inv_irq->handler(inv_irq, inv_irq->opaque, inv_irq->n, !level);
 }
 
 qemu_irq qemu_irq_invert(qemu_irq irq)
diff --git a/hw/irq.h b/hw/irq.h
index 5daae44..d0f83e3 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,9 +3,7 @@
 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
-/* FIXME: Rmove one of these.  */
-typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
-typedef void SetIRQFunc(void *opaque, int irq_num, int level);
+typedef void (*qemu_irq_handler)(qemu_irq irq, void *opaque, int n, int level);
 
 void qemu_set_irq(qemu_irq irq, int level);
 
diff --git a/hw/lance.c b/hw/lance.c
index b6b04dd..de9e9bd 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -48,7 +48,7 @@ typedef struct {
     PCNetState state;
 } SysBusPCNetState;
 
-static void parent_lance_reset(void *opaque, int irq, int level)
+static void parent_lance_reset(qemu_irq irq, void *opaque, int n, int level)
 {
     SysBusPCNetState *d = opaque;
     if (level)
diff --git a/hw/max7310.c b/hw/max7310.c
index c302eb6..dc0f8ea 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -161,7 +161,7 @@ static const VMStateDescription vmstate_max7310 = {
     }
 };
 
-static void max7310_gpio_set(void *opaque, int line, int level)
+static void max7310_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     MAX7310State *s = (MAX7310State *) opaque;
     if (line >= ARRAY_SIZE(s->handler) || line  < 0)
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index c107de8..eca6e63 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -226,13 +226,13 @@ static void m5206_mbar_update(m5206_mbar_state *s)
     m68k_set_irq_level(s->env, level, vector);
 }
 
-static void m5206_mbar_set_irq(void *opaque, int irq, int level)
+static void m5206_mbar_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     if (level) {
-        s->ipr |= 1 << irq;
+        s->ipr |= 1 << n;
     } else {
-        s->ipr &= ~(1 << irq);
+        s->ipr &= ~(1 << n);
     }
     m5206_mbar_update(s);
 }
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index f01bd32..620c10e 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -105,15 +105,17 @@ static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
     mcf_intc_update(s);
 }
 
-static void mcf_intc_set_irq(void *opaque, int irq, int level)
+static void mcf_intc_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     mcf_intc_state *s = (mcf_intc_state *)opaque;
-    if (irq >= 64)
+    if (n >= 64) {
         return;
-    if (level)
-        s->ipr |= 1ull << irq;
-    else
-        s->ipr &= ~(1ull << irq);
+    }
+    if (level) {
+        s->ipr |= 1ull << n;
+    } else {
+        s->ipr &= ~(1ull << n);
+    }
     mcf_intc_update(s);
 }
 
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index 7c59382..200832d 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -32,10 +32,11 @@ void pic_info(Monitor *mon)
 void irq_info(Monitor *mon)
 {}
 
-static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
+static void microblaze_pic_cpu_handler(qemu_irq irq, void *opaque, int n,
+                                       int level)
 {
     CPUState *env = (CPUState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+    int type = n ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level)
         cpu_interrupt(env, type);
diff --git a/hw/mips_int.c b/hw/mips_int.c
index c30954c..434b47a 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -40,17 +40,17 @@ void cpu_mips_update_irq(CPUState *env)
         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
-static void cpu_mips_irq_request(void *opaque, int irq, int level)
+static void cpu_mips_irq_request(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = (CPUState *)opaque;
 
-    if (irq < 0 || irq > 7)
+    if (n < 0 || n > 7) {
         return;
-
+    }
     if (level) {
-        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+        env->CP0_Cause |= 1 << (n + CP0Ca_IP);
     } else {
-        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+        env->CP0_Cause &= ~(1 << (n + CP0Ca_IP));
     }
     cpu_mips_update_irq(env);
 }
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index ead3a00..da1bf6e 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -114,7 +114,7 @@ static void audio_init(qemu_irq *pic)
 #define MAGNUM_BIOS_SIZE_MAX 0x7e000
 #define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index a8f9d15..bd86636 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -763,7 +763,7 @@ static void main_cpu_reset(void *opaque)
     }
 }
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 1b6cb77..6d5fc8f 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -61,17 +61,17 @@ mst_fpga_update_gpio(mst_irq_state *s)
 }
 
 static void
-mst_fpga_set_irq(void *opaque, int irq, int level)
+mst_fpga_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
 	mst_irq_state *s = (mst_irq_state *)opaque;
 
 	if (level)
-		s->prev_level |= 1u << irq;
+		s->prev_level |= 1u << n;
 	else
-		s->prev_level &= ~(1u << irq);
+		s->prev_level &= ~(1u << n);
 
-	if(s->intmskena & (1u << irq)) {
-		s->intsetclr = 1u << irq;
+	if (s->intmskena & (1u << n)) {
+		s->intsetclr = 1u << n;
 		qemu_set_irq(s->parent[0], level);
 	}
 }
diff --git a/hw/musicpal.c b/hw/musicpal.c
index d44c5a0..fa86180 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -519,11 +519,12 @@ static void lcd_invalidate(void *opaque)
 {
 }
 
-static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
+static void musicpal_lcd_gpio_brigthness_in(qemu_irq irq, void *opaque, int n,
+                                            int level)
 {
     musicpal_lcd_state *s = opaque;
-    s->brightness &= ~(1 << irq);
-    s->brightness |= level << irq;
+    s->brightness &= ~(1 << n);
+    s->brightness |= level << n;
 }
 
 static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset)
@@ -652,14 +653,14 @@ static void mv88w8618_pic_update(mv88w8618_pic_state *s)
     qemu_set_irq(s->parent_irq, (s->level & s->enabled));
 }
 
-static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
+static void mv88w8618_pic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     mv88w8618_pic_state *s = opaque;
 
     if (level) {
-        s->level |= 1 << irq;
+        s->level |= 1 << n;
     } else {
-        s->level &= ~(1 << irq);
+        s->level &= ~(1 << n);
     }
     mv88w8618_pic_update(s);
 }
@@ -1165,7 +1166,8 @@ static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
     }
 }
 
-static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
+static void musicpal_gpio_pin_event(qemu_irq irq, void *opaque, int pin,
+                                    int level)
 {
     musicpal_gpio_state *s = opaque;
     uint32_t mask = 1 << pin;
diff --git a/hw/nseries.c b/hw/nseries.c
index 04a028d..21cbf6c 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -122,7 +122,7 @@ struct n800_s {
 
 #define N8X0_BD_ADDR			0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
 
-static void n800_mmc_cs_cb(void *opaque, int line, int level)
+static void n800_mmc_cs_cb(qemu_irq irq, void *opaque, int line, int level)
 {
     /* TODO: this seems to actually be connected to the menelaus, to
      * which also both MMC slots connect.  */
@@ -754,7 +754,7 @@ static void n8x0_uart_setup(struct n800_s *s)
     omap_uart_attach(s->cpu->uart[BT_UART], radio);
 }
 
-static void n8x0_usb_power_cb(void *opaque, int line, int level)
+static void n8x0_usb_power_cb(qemu_irq irq, void *opaque, int line, int level)
 {
     struct n800_s *s = opaque;
 
diff --git a/hw/omap.h b/hw/omap.h
index d305779..4e31860 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -979,7 +979,7 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr);
 void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
                 uint32_t value);
 
-void omap_mpu_wakeup(void *opaque, int irq, int req);
+void omap_mpu_wakeup(qemu_irq irq, void *opaque, int n, int req);
 
 # define OMAP_BAD_REG(paddr)		\
         fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n",	\
diff --git a/hw/omap1.c b/hw/omap1.c
index 8649dbd..cf2191d 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -150,13 +150,13 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
 #define INT_FALLING_EDGE	0
 #define INT_LOW_LEVEL		1
 
-static void omap_set_intr(void *opaque, int irq, int req)
+static void omap_set_intr(qemu_irq irq, void *opaque, int line, int req)
 {
     struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
     uint32_t rise;
 
-    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-    int n = irq & 31;
+    struct omap_intr_handler_bank_s *bank = &ih->bank[line >> 5];
+    int n = line & 31;
 
     if (req) {
         rise = ~bank->irqs & (1 << n);
@@ -177,13 +177,13 @@ static void omap_set_intr(void *opaque, int irq, int req)
 }
 
 /* Simplified version with no edge detection */
-static void omap_set_intr_noedge(void *opaque, int irq, int req)
+static void omap_set_intr_noedge(qemu_irq irq, void *opaque, int line, int req)
 {
     struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
     uint32_t rise;
 
-    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-    int n = irq & 31;
+    struct omap_intr_handler_bank_s *bank = &ih->bank[line >> 5];
+    int n = line & 31;
 
     if (req) {
         rise = ~bank->inputs & (1 << n);
@@ -358,7 +358,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
     case 0x9c:	/* ISR */
         for (i = 0; i < 32; i ++)
             if (value & (1 << i)) {
-                omap_set_intr(s, 32 * bank_no + i, 1);
+                omap_set_intr(NULL, s, 32 * bank_no + i, 1);
                 return;
             }
         return;
@@ -732,7 +732,7 @@ static void omap_timer_tick(void *opaque)
     omap_timer_update(timer);
 }
 
-static void omap_timer_clk_update(void *opaque, int line, int on)
+static void omap_timer_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
 
@@ -2556,7 +2556,7 @@ struct omap_mpuio_s {
     int clk;
 };
 
-static void omap_mpuio_set(void *opaque, int line, int level)
+static void omap_mpuio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
     uint16_t prev = s->inputs;
@@ -2747,7 +2747,7 @@ static void omap_mpuio_reset(struct omap_mpuio_s *s)
     s->clk = 1;
 }
 
-static void omap_mpuio_onoff(void *opaque, int line, int on)
+static void omap_mpuio_onoff(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
 
@@ -2819,7 +2819,7 @@ struct omap_gpio_s {
     uint16_t pins;
 };
 
-static void omap_gpio_set(void *opaque, int line, int level)
+static void omap_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
     uint16_t prev = s->inputs;
@@ -3222,7 +3222,7 @@ static void omap_pwl_reset(struct omap_mpu_state_s *s)
     omap_pwl_update(s);
 }
 
-static void omap_pwl_clk_update(void *opaque, int line, int on)
+static void omap_pwl_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 
@@ -4274,7 +4274,8 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
     return s;
 }
 
-static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
+static void omap_mcbsp_i2s_swallow(qemu_irq irq, void *opaque, int line,
+                                   int level)
 {
     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
 
@@ -4284,7 +4285,8 @@ static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
     }
 }
 
-static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
+static void omap_mcbsp_i2s_start(qemu_irq irq, void *opaque, int line,
+                                 int level)
 {
     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
 
@@ -4421,7 +4423,7 @@ static CPUWriteMemoryFunc * const omap_lpg_writefn[] = {
     omap_badwidth_write8,
 };
 
-static void omap_lpg_clk_update(void *opaque, int line, int on)
+static void omap_lpg_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
 
@@ -4560,7 +4562,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map)
     }
 }
 
-void omap_mpu_wakeup(void *opaque, int irq, int req)
+void omap_mpu_wakeup(qemu_irq irq, void *opaque, int n, int req)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
 
diff --git a/hw/omap2.c b/hw/omap2.c
index bd1b35e..ec73775 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -190,7 +190,7 @@ static void omap_gp_timer_match(void *opaque)
     omap_gp_timer_intr(timer, GPT_MAT_IT);
 }
 
-static void omap_gp_timer_input(void *opaque, int line, int on)
+static void omap_gp_timer_input(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
     int trigger;
@@ -220,7 +220,8 @@ static void omap_gp_timer_input(void *opaque, int line, int on)
     }
 }
 
-static void omap_gp_timer_clk_update(void *opaque, int line, int on)
+static void omap_gp_timer_clk_update(qemu_irq irq, void *opaque, int line,
+                                     int on)
 {
     struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
 
@@ -625,7 +626,8 @@ static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line)
     omap_gpio_module_wake(s, line);
 }
 
-static void omap_gpio_module_set(void *opaque, int line, int level)
+static void omap_gpio_module_set(qemu_irq irq, void *opaque, int line,
+                                 int level)
 {
     struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 
diff --git a/hw/omap_dma.c b/hw/omap_dma.c
index 3e718ba..4006d81 100644
--- a/hw/omap_dma.c
+++ b/hw/omap_dma.c
@@ -1542,7 +1542,7 @@ static CPUWriteMemoryFunc * const omap_dma_writefn[] = {
     omap_badwidth_write16,
 };
 
-static void omap_dma_request(void *opaque, int drq, int req)
+static void omap_dma_request(qemu_irq irq, void *opaque, int drq, int req)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     /* The request pins are level triggered in QEMU.  */
@@ -1556,7 +1556,7 @@ static void omap_dma_request(void *opaque, int drq, int req)
 }
 
 /* XXX: this won't be needed once soc_dma knows about clocks.  */
-static void omap_dma_clk_update(void *opaque, int line, int on)
+static void omap_dma_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int i;
@@ -1656,7 +1656,7 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_setcaps(s);
     omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
     omap_dma_reset(s->dma);
-    omap_dma_clk_update(s, 0, 1);
+    omap_dma_clk_update(NULL, s, 0, 1);
 
     iomemtype = cpu_register_io_memory(omap_dma_readfn,
                     omap_dma_writefn, s);
@@ -2063,7 +2063,7 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_setcaps(s);
     omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
     omap_dma_reset(s->dma);
-    omap_dma_clk_update(s, 0, !!s->dma->freq);
+    omap_dma_clk_update(NULL, s, 0, !!s->dma->freq);
 
     iomemtype = cpu_register_io_memory(omap_dma4_readfn,
                     omap_dma4_writefn, s);
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index 15cbf06..ec8719e 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -552,7 +552,7 @@ static CPUWriteMemoryFunc * const omap_mmc_writefn[] = {
     omap_badwidth_write16,
 };
 
-static void omap_mmc_cover_cb(void *opaque, int line, int level)
+static void omap_mmc_cover_cb(qemu_irq irq, void *opaque, int line, int level)
 {
     struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
 
diff --git a/hw/openpic.c b/hw/openpic.c
index ac21993..74730ee 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -399,7 +399,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
     }
 }
 
-static void openpic_set_irq(void *opaque, int n_IRQ, int level)
+static void openpic_set_irq(qemu_irq irq, void *opaque, int n_IRQ, int level)
 {
     openpic_t *opp = opaque;
     IRQ_src_t *src;
@@ -832,8 +832,8 @@ static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t v
     case 0x70:
         idx = (addr - 0x40) >> 4;
         write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
-        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
-        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
+        openpic_set_irq(NULL, opp, opp->irq_ipi0 + idx, 1);
+        openpic_set_irq(NULL, opp, opp->irq_ipi0 + idx, 0);
         break;
 #endif
     case 0x80: /* PCTP */
diff --git a/hw/palm.c b/hw/palm.c
index 8db133d..88448c2 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -131,7 +131,7 @@ static void palmte_button_event(void *opaque, int keycode)
                         !(keycode & 0x80));
 }
 
-static void palmte_onoff_gpios(void *opaque, int line, int level)
+static void palmte_onoff_gpios(qemu_irq irq, void *opaque, int line, int level)
 {
     switch (line) {
     case 0:
diff --git a/hw/pc.c b/hw/pc.c
index ae31e2e..20057ca 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -77,7 +77,7 @@ struct e820_table {
 
 static struct e820_table e820_table;
 
-void isa_irq_handler(void *opaque, int n, int level)
+void isa_irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     IsaIrqState *isa = (IsaIrqState *)opaque;
 
@@ -158,11 +158,11 @@ int cpu_get_pic_interrupt(CPUState *env)
     return intno;
 }
 
-static void pic_irq_request(void *opaque, int irq, int level)
+static void pic_irq_request(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = first_cpu;
 
-    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
+    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", n);
     if (env->apic_state) {
         while (env) {
             if (apic_accept_pic_intr(env))
@@ -378,7 +378,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     rtc_set_memory(s, 0x39, val);
 }
 
-static void handle_a20_line_change(void *opaque, int irq, int level)
+static void handle_a20_line_change(qemu_irq irq, void *opaque, int n,
+                                   int level)
 {
     CPUState *cpu = opaque;
 
@@ -750,7 +751,7 @@ int cpu_is_bsp(CPUState *env)
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
    BIOS will read it and start S3 resume at POST Entry */
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
+void pc_cmos_set_s3_resume(qemu_irq irq, void *opaque, int n, int level)
 {
     ISADevice *s = opaque;
 
@@ -759,7 +760,7 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
     }
 }
 
-void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
+void pc_acpi_smi_interrupt(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *s = opaque;
 
@@ -927,7 +928,7 @@ void pc_vga_init(PCIBus *pci_bus)
     }
 }
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/pc.h b/hw/pc.h
index 0e52933..82b902f 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -29,8 +29,6 @@ ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq
 
 typedef struct PicState2 PicState2;
 extern PicState2 *isa_pic;
-void pic_set_irq(int irq, int level);
-void pic_set_irq_new(void *opaque, int irq, int level);
 qemu_irq *i8259_init(qemu_irq parent_irq);
 int pic_read_irq(PicState2 *s);
 void pic_update_irq(PicState2 *s);
@@ -44,7 +42,7 @@ typedef struct isa_irq_state {
     qemu_irq *ioapic;
 } IsaIrqState;
 
-void isa_irq_handler(void *opaque, int n, int level);
+void isa_irq_handler(qemu_irq irq, void *opaque, int n, int level);
 
 /* i8254.c */
 
@@ -82,8 +80,8 @@ void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out);
 extern int fd_bootchk;
 
 void pc_register_ferr_irq(qemu_irq irq);
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
-void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
+void pc_cmos_set_s3_resume(qemu_irq irq, void *opaque, int n, int level);
+void pc_acpi_smi_interrupt(qemu_irq irq, void *opaque, int n, int level);
 
 void pc_cpus_init(const char *cpu_model);
 void pc_memory_init(ram_addr_t ram_size,
diff --git a/hw/pci.c b/hw/pci.c
index cbbd1dd..edca65a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -72,7 +72,7 @@ static struct BusInfo pci_bus_info = {
 };
 
 static void pci_update_mappings(PCIDevice *d);
-static void pci_set_irq(void *opaque, int irq_num, int level);
+static void pci_set_irq(qemu_irq irq, void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
@@ -1037,7 +1037,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 /* generic PCI irq support */
 
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
-static void pci_set_irq(void *opaque, int irq_num, int level)
+static void pci_set_irq(qemu_irq irq, void *opaque, int irq_num, int level)
 {
     PCIDevice *pci_dev = opaque;
     int change;
diff --git a/hw/pl061.c b/hw/pl061.c
index 7b1b636..e9490bb 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -209,12 +209,12 @@ static void pl061_reset(pl061_state *s)
   s->cr = 0xff;
 }
 
-static void pl061_set_irq(void * opaque, int irq, int level)
+static void pl061_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     pl061_state *s = (pl061_state *)opaque;
     uint8_t mask;
 
-    mask = 1 << irq;
+    mask = 1 << n;
     if ((s->dir & mask) == 0) {
         s->data &= ~mask;
         if (level)
diff --git a/hw/pl190.c b/hw/pl190.c
index a4bc9c1..a00d86b 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -54,14 +54,14 @@ static void pl190_update(pl190_state *s)
     qemu_set_irq(s->fiq, set);
 }
 
-static void pl190_set_irq(void *opaque, int irq, int level)
+static void pl190_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     pl190_state *s = (pl190_state *)opaque;
 
     if (level)
-        s->level |= 1u << irq;
+        s->level |= 1u << n;
     else
-        s->level &= ~(1u << irq);
+        s->level &= ~(1u << n);
     pl190_update(s);
 }
 
diff --git a/hw/ppc.c b/hw/ppc.c
index 2a77eb9..2aef868 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -64,7 +64,7 @@ static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
 }
 
 /* PowerPC 6xx / 7xx internal IRQ controller */
-static void ppc6xx_set_irq (void *opaque, int pin, int level)
+static void ppc6xx_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -154,7 +154,7 @@ void ppc6xx_irq_init (CPUState *env)
 
 #if defined(TARGET_PPC64)
 /* PowerPC 970 internal IRQ controller */
-static void ppc970_set_irq (void *opaque, int pin, int level)
+static void ppc970_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -238,7 +238,7 @@ void ppc970_irq_init (CPUState *env)
 #endif /* defined(TARGET_PPC64) */
 
 /* PowerPC 40x internal IRQ controller */
-static void ppc40x_set_irq (void *opaque, int pin, int level)
+static void ppc40x_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -316,7 +316,7 @@ void ppc40x_irq_init (CPUState *env)
 }
 
 /* PowerPC E500 internal IRQ controller */
-static void ppce500_set_irq (void *opaque, int pin, int level)
+static void ppce500_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 37a3948..732b17d 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -147,7 +147,7 @@ static void ppcuic_trigger_irq (ppcuic_t *uic)
     }
 }
 
-static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+static void ppcuic_set_irq (qemu_irq irq, void *opaque, int irq_num, int level)
 {
     ppcuic_t *uic;
     uint32_t mask, sr;
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 16c9950..fd1ca86 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -547,7 +547,7 @@ static CPUReadMemoryFunc * const PPC_prep_io_read[] = {
 
 #define NVRAM_SIZE        0x2000
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9095386..aef4259 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2019,7 +2019,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
     return s;
 }
 
-static void pxa2xx_reset(void *opaque, int line, int level)
+static void pxa2xx_reset(qemu_irq irq, void *opaque, int line, int level)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f354f4b..7a7e538 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -86,7 +86,7 @@ static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
     0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
 };
 
-static void pxa2xx_gpio_set(void *opaque, int line, int level)
+static void pxa2xx_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
     int bank;
diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index be1309f..0e46d9e 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -121,7 +121,8 @@ static CPUWriteMemoryFunc * const pxa2xx_pcmcia_io_writefn[] = {
     pxa2xx_pcmcia_io_write,
 };
 
-static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
+static void pxa2xx_pcmcia_set_irq(qemu_irq irq, void *opaque, int line,
+                                  int level)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     if (!s->irq)
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 0a98342..67163ce 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -67,16 +67,16 @@ static void pxa2xx_pic_update(void *opaque)
 
 /* Note: Here level means state of the signal on a pin, not
  * IRQ/FIQ distinction as in PXA Developer Manual.  */
-static void pxa2xx_pic_set_irq(void *opaque, int irq, int level)
+static void pxa2xx_pic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-    int int_set = (irq >= 32);
-    irq &= 31;
+    int int_set = (n >= 32);
+    n &= 31;
 
     if (level)
-        s->int_pending[int_set] |= 1 << irq;
+        s->int_pending[int_set] |= 1 << n;
     else
-        s->int_pending[int_set] &= ~(1 << irq);
+        s->int_pending[int_set] &= ~(1 << n);
 
     pxa2xx_pic_update(opaque);
 }
diff --git a/hw/r2d.c b/hw/r2d.c
index 38c4f6a..eb8e6e0 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -114,7 +114,7 @@ static void update_irl(r2d_fpga_t *fpga)
     qemu_set_irq(fpga->irl, irl ^ 15);
 }
 
-static void r2d_fpga_irq_set(void *opaque, int n, int level)
+static void r2d_fpga_irq_set(qemu_irq irq, void *opaque, int n, int level)
 {
     r2d_fpga_t *fpga = opaque;
     if (level)
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 2a8233a..09260de 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -459,14 +459,15 @@ static void update_jazz_irq(rc4030State *s)
         qemu_irq_lower(s->jazz_bus_irq);
 }
 
-static void rc4030_irq_jazz_request(void *opaque, int irq, int level)
+static void rc4030_irq_jazz_request(qemu_irq irq, void *opaque, int n,
+                                    int level)
 {
     rc4030State *s = opaque;
 
     if (level) {
-        s->isr_jazz |= 1 << irq;
+        s->isr_jazz |= 1 << n;
     } else {
-        s->isr_jazz &= ~(1 << irq);
+        s->isr_jazz &= ~(1 << n);
     }
 
     update_jazz_irq(s);
diff --git a/hw/sbi.c b/hw/sbi.c
index c4adc09..0783efa 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -47,7 +47,7 @@ typedef struct SBIState {
 
 #define SBI_SIZE (SBI_NREGS * 4)
 
-static void sbi_set_irq(void *opaque, int irq, int level)
+static void sbi_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
 }
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index da36d32..8bb1b07 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -71,7 +71,7 @@ void sh_intc_toggle_source(struct intc_source *source,
   }
 }
 
-static void sh_intc_set_irq (void *opaque, int n, int level)
+static void sh_intc_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
   struct intc_desc *desc = opaque;
   struct intc_source *source = &(desc->sources[n]);
@@ -467,7 +467,7 @@ int sh_intc_init(struct intc_desc *desc,
 
 /* Assert level <n> IRL interrupt. 
    0:deassert. 1:lowest priority,... 15:highest priority. */
-void sh_intc_set_irl(void *opaque, int n, int level)
+void sh_intc_set_irl(qemu_irq irq, void *opaque, int n, int level)
 {
     struct intc_source *s = opaque;
     int i, irl = level ^ 15;
diff --git a/hw/sh_intc.h b/hw/sh_intc.h
index c117d6f..2dbe391 100644
--- a/hw/sh_intc.h
+++ b/hw/sh_intc.h
@@ -75,6 +75,6 @@ int sh_intc_init(struct intc_desc *desc,
 		 struct intc_prio_reg *prio_regs,
 		 int nr_prio_regs);
 
-void sh_intc_set_irl(void *opaque, int n, int level);
+void sh_intc_set_irl(qemu_irq irq, void *opaque, int n, int level);
 
 #endif /* __SH_INTC_H__ */
diff --git a/hw/sharpsl.h b/hw/sharpsl.h
index c5ccf79..ca7e001 100644
--- a/hw/sharpsl.h
+++ b/hw/sharpsl.h
@@ -13,7 +13,6 @@
 typedef struct ScoopInfo ScoopInfo;
 ScoopInfo *scoop_init(PXA2xxState *cpu,
                 int instance, target_phys_addr_t target_base);
-void scoop_gpio_set(void *opaque, int line, int level);
 qemu_irq *scoop_gpio_in_get(ScoopInfo *s);
 void scoop_gpio_out_set(ScoopInfo *s, int line,
                 qemu_irq handler);
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index b76d3ac..174ebca 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -317,14 +317,14 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
  * "irq" here is the bit number in the system interrupt register to
  * separate serial and keyboard interrupts sharing a level.
  */
-static void slavio_set_irq(void *opaque, int irq, int level)
+static void slavio_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     SLAVIO_INTCTLState *s = opaque;
-    uint32_t mask = 1 << irq;
-    uint32_t pil = intbit_to_level[irq];
+    uint32_t mask = 1 << n;
+    uint32_t pil = intbit_to_level[n];
     unsigned int i;
 
-    DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, irq, pil,
+    DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, n, pil,
             level);
     if (pil > 0) {
         if (level) {
@@ -364,12 +364,12 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
     slavio_check_interrupts(s, 1);
 }
 
-static void slavio_set_irq_all(void *opaque, int irq, int level)
+static void slavio_set_irq_all(qemu_irq irq, void *opaque, int n, int level)
 {
-    if (irq < 32) {
-        slavio_set_irq(opaque, irq, level);
+    if (n < 32) {
+        slavio_set_irq(irq, opaque, n, level);
     } else {
-        slavio_set_timer_irq_cpu(opaque, irq - 32, level);
+        slavio_set_timer_irq_cpu(opaque, n - 32, level);
     }
 }
 
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 5ae628d..337c2e1 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -95,7 +95,8 @@ static void slavio_misc_reset(DeviceState *d)
     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
 }
 
-static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
+static void slavio_set_power_fail(qemu_irq irq, void *opaque, int n,
+                                  int power_failing)
 {
     MiscState *s = opaque;
 
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index b521707..1e629da 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -127,7 +127,7 @@ void ledma_memory_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void dma_set_irq(void *opaque, int irq, int level)
+static void dma_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     DMAState *s = opaque;
     if (level) {
diff --git a/hw/spitz.c b/hw/spitz.c
index 4f82e24..010316c 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -253,7 +253,8 @@ static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
     s->sense_state = sense;
 }
 
-static void spitz_keyboard_strobe(void *opaque, int line, int level)
+static void spitz_keyboard_strobe(qemu_irq irq, void *opaque, int line,
+                                  int level)
 {
     SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
 
@@ -649,7 +650,7 @@ static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
     return 0;
 }
 
-static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
+static void corgi_ssp_gpio_cs(qemu_irq irq, void *opaque, int line, int level)
 {
     CorgiSSPState *s = (CorgiSSPState *)opaque;
     assert(line >= 0 && line < 3);
@@ -769,7 +770,7 @@ static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
 #define SPITZ_GPIO_WM	5
 
 #ifdef HAS_AUDIO
-static void spitz_wm8750_addr(void *opaque, int line, int level)
+static void spitz_wm8750_addr(qemu_irq irq, void *opaque, int line, int level)
 {
     i2c_slave *wm = (i2c_slave *) opaque;
     if (level)
@@ -790,7 +791,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
     /* Attach a WM8750 to the bus */
     wm = i2c_create_slave(bus, "wm8750", 0);
 
-    spitz_wm8750_addr(wm, 0, 0);
+    spitz_wm8750_addr(NULL, wm, 0, 0);
     pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_WM,
                     qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
     /* .. and to the sound interface.  */
@@ -810,7 +811,7 @@ static void spitz_akita_i2c_setup(PXA2xxState *cpu)
 
 /* Other peripherals */
 
-static void spitz_out_switch(void *opaque, int line, int level)
+static void spitz_out_switch(qemu_irq irq, void *opaque, int line, int level)
 {
     switch (line) {
     case 0:
@@ -882,7 +883,8 @@ static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
 
 static int spitz_hsync;
 
-static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
+static void spitz_lcd_hsync_handler(qemu_irq irq, void *opaque, int line,
+                                    int level)
 {
     PXA2xxState *cpu = (PXA2xxState *) opaque;
     qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_HSYNC], spitz_hsync);
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index b632825..140f661 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -268,7 +268,7 @@ static void ssd0323_invalidate_display(void * opaque)
 }
 
 /* Command/data input.  */
-static void ssd0323_cd(void *opaque, int n, int level)
+static void ssd0323_cd(qemu_irq irq, void *opaque, int n, int level)
 {
     ssd0323_state *s = (ssd0323_state *)opaque;
     DPRINTF("%s mode\n", level ? "Data" : "Command");
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5755f8a..45a11dd 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -974,7 +974,8 @@ static void stellaris_adc_update(stellaris_adc_state *s)
     }
 }
 
-static void stellaris_adc_trigger(void *opaque, int irq, int level)
+static void stellaris_adc_trigger(qemu_irq irq, void *opaque, int line,
+                                  int level)
 {
     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
     int n;
@@ -1215,7 +1216,8 @@ typedef struct {
     SSIBus *bus[2];
 } stellaris_ssi_bus_state;
 
-static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
+static void stellaris_ssi_bus_select(qemu_irq irq, void *opaque, int line,
+                                     int level)
 {
     stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
 
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 7d7542d..6c6f5bb 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -148,13 +148,13 @@ static void sun4c_check_interrupts(void *opaque)
 /*
  * "irq" here is the bit number in the system interrupt register
  */
-static void sun4c_set_irq(void *opaque, int irq, int level)
+static void sun4c_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     Sun4c_INTCTLState *s = opaque;
-    uint32_t mask = 1 << irq;
-    uint32_t pil = intbit_to_level[irq];
+    uint32_t mask = 1 << n;
+    uint32_t pil = intbit_to_level[n];
 
-    DPRINTF("Set irq %d -> pil %d level %d\n", irq, pil,
+    DPRINTF("Set irq %d -> pil %d level %d\n", n, pil,
             level);
     if (pil > 0) {
         if (level) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index e4ca8f3..bbfa4f4 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -255,23 +255,23 @@ void cpu_check_irqs(CPUState *env)
     }
 }
 
-static void cpu_set_irq(void *opaque, int irq, int level)
+static void cpu_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = opaque;
 
     if (level) {
-        DPRINTF("Raise CPU IRQ %d\n", irq);
+        DPRINTF("Raise CPU IRQ %d\n", n);
         env->halted = 0;
-        env->pil_in |= 1 << irq;
+        env->pil_in |= 1 << n;
         cpu_check_irqs(env);
     } else {
-        DPRINTF("Lower CPU IRQ %d\n", irq);
-        env->pil_in &= ~(1 << irq);
+        DPRINTF("Lower CPU IRQ %d\n", n);
+        env->pil_in &= ~(1 << n);
         cpu_check_irqs(env);
     }
 }
 
-static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+static void dummy_cpu_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
 }
 
@@ -291,7 +291,7 @@ static void secondary_cpu_reset(void *opaque)
     env->halted = 1;
 }
 
-static void cpu_halt_signal(void *opaque, int irq, int level)
+static void cpu_halt_signal(qemu_irq irq, void *opaque, int n, int level)
 {
     if (level && cpu_single_env)
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 40b5f1f..0df1051 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -299,18 +299,18 @@ static void cpu_kick_irq(CPUState *env)
     cpu_check_irqs(env);
 }
 
-static void cpu_set_irq(void *opaque, int irq, int level)
+static void cpu_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = opaque;
 
     if (level) {
-        CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
+        CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", n);
         env->halted = 0;
-        env->pil_in |= 1 << irq;
+        env->pil_in |= 1 << n;
         cpu_check_irqs(env);
     } else {
-        CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
-        env->pil_in &= ~(1 << irq);
+        CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", n);
+        env->pil_in &= ~(1 << n);
         cpu_check_irqs(env);
     }
 }
@@ -532,7 +532,7 @@ static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
     }
 }
 
-static void dummy_isa_irq_handler(void *opaque, int n, int level)
+static void dummy_isa_irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
 }
 
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index f3a1767..d108712 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -67,15 +67,15 @@ static void syborg_int_update(SyborgIntState *s)
     qemu_set_irq(s->parent_irq, s->pending_count > 0);
 }
 
-static void syborg_int_set_irq(void *opaque, int irq, int level)
+static void syborg_int_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     SyborgIntState *s = (SyborgIntState *)opaque;
 
-    if (s->flags[irq].level == level)
+    if (s->flags[n].level == level)
         return;
 
-    s->flags[irq].level = level;
-    if (s->flags[irq].enabled) {
+    s->flags[n].level = level;
+    if (s->flags[n].enabled) {
         if (level)
             s->pending_count++;
         else
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index e0c5e5f..ff8165a 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -135,7 +135,7 @@ qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s)
     return s->gpio_in;
 }
 
-static void tc6393xb_gpio_set(void *opaque, int line, int level)
+static void tc6393xb_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
 //    TC6393xbState *s = opaque;
 
@@ -178,14 +178,15 @@ qemu_irq tc6393xb_l3v_get(TC6393xbState *s)
     return s->l3v;
 }
 
-static void tc6393xb_l3v(void *opaque, int line, int level)
+static void tc6393xb_l3v(qemu_irq irq, void *opaque, int line, int level)
 {
     TC6393xbState *s = opaque;
     s->blank = !level;
     fprintf(stderr, "L3V: %d\n", level);
 }
 
-static void tc6393xb_sub_irq(void *opaque, int line, int level) {
+static void tc6393xb_sub_irq(qemu_irq irq, void *opaque, int line, int level)
+{
     TC6393xbState *s = opaque;
     uint8_t isr = s->scr.ISR;
     if (level)
diff --git a/hw/tosa.c b/hw/tosa.c
index fbe8d8c..2a1954b 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -62,7 +62,7 @@ static void tosa_microdrive_attach(PXA2xxState *cpu)
     }
 }
 
-static void tosa_out_switch(void *opaque, int line, int level)
+static void tosa_out_switch(qemu_irq irq, void *opaque, int line, int level)
 {
     switch (line) {
         case 0:
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 4864be5..ab28667 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -678,7 +678,8 @@ static void tusb_power_tick(void *opaque)
     }
 }
 
-static void tusb_musb_core_intr(void *opaque, int source, int level)
+static void tusb_musb_core_intr(qemu_irq irq, void *opaque, int source,
+                                int level)
 {
     TUSBState *s = (TUSBState *) opaque;
     uint16_t otg_status = s->otg_status;
diff --git a/hw/twl92230.c b/hw/twl92230.c
index e61f17f..3ab8dfd 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -183,7 +183,7 @@ static void menelaus_reset(i2c_slave *i2c)
     menelaus_update(s);
 }
 
-static void menelaus_gpio_set(void *opaque, int line, int level)
+static void menelaus_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     MenelausState *s = (MenelausState *) opaque;
 
@@ -192,7 +192,8 @@ static void menelaus_gpio_set(void *opaque, int line, int level)
     s->inputs |= level << line;
 }
 
-static void menelaus_pwrbtn_set(void *opaque, int line, int level)
+static void menelaus_pwrbtn_set(qemu_irq irq, void *opaque, int line,
+                                int level)
 {
     MenelausState *s = (MenelausState *) opaque;
 
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 391f5b8..49a780a 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -50,15 +50,15 @@ static void vpb_sic_update_pic(vpb_sic_state *s)
     }
 }
 
-static void vpb_sic_set_irq(void *opaque, int irq, int level)
+static void vpb_sic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     vpb_sic_state *s = (vpb_sic_state *)opaque;
     if (level)
-        s->level |= 1u << irq;
+        s->level |= 1u << n;
     else
-        s->level &= ~(1u << irq);
-    if (s->pic_enable & (1u << irq))
-        qemu_set_irq(s->parent[irq], level);
+        s->level &= ~(1u << n);
+    if (s->pic_enable & (1u << n))
+        qemu_set_irq(s->parent[n], level);
     vpb_sic_update(s);
 }
 
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 8ef6474..20b0267 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -126,7 +126,7 @@ static CPUWriteMemoryFunc * const pic_write[] = {
     &pic_writel,
 };
 
-static void irq_handler(void *opaque, int irq, int level)
+static void irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     struct xlx_pic *p = opaque;
 
@@ -138,9 +138,9 @@ static void irq_handler(void *opaque, int irq, int level)
     /* Update source flops. Don't clear unless level triggered.
        Edge triggered interrupts only go away when explicitely acked to
        the interrupt controller.  */
-    if (!(p->c_kind_of_intr & (1 << irq)) || level) {
-        p->regs[R_ISR] &= ~(1 << irq);
-        p->regs[R_ISR] |= (level << irq);
+    if (!(p->c_kind_of_intr & (1 << n)) || level) {
+        p->regs[R_ISR] &= ~(1 << n);
+        p->regs[R_ISR] |= (level << n);
     }
     update_irq(p);
 }
diff --git a/hw/zaurus.c b/hw/zaurus.c
index db6ba75..94c4ad7 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -153,7 +153,7 @@ static CPUWriteMemoryFunc * const scoop_writefn[] = {
     scoop_writeb,
 };
 
-void scoop_gpio_set(void *opaque, int line, int level)
+static void scoop_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (7 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 08/16] Pass IRQ object on handler invocation Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-12 12:21   ` Paul Brook
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround Jan Kiszka
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

This patch allows to optionally attach a message to an IRQ event. The
message can contain a payload reference and a callback that the IRQ
handler may invoke to report the delivery result. The former can be used
to model message signaling interrupts, the latter to cleanly implement
IRQ de-coalescing logics.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/irq.c |   37 ++++++++++++++++++++++++++++++++++++-
 hw/irq.h |   38 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/hw/irq.c b/hw/irq.c
index 24fb09d..db5136b 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -28,12 +28,31 @@ struct IRQState {
     qemu_irq_handler handler;
     void *opaque;
     int n;
+    IRQMsg *msg;
 };
 
-void qemu_set_irq(qemu_irq irq, int level)
+void qemu_set_irq_msg(qemu_irq irq, int level, IRQMsg *msg)
 {
     if (irq) {
+        irq->msg = msg;
         irq->handler(irq, irq->opaque, irq->n, level);
+        irq->msg = NULL;
+    }
+}
+
+void *qemu_irq_get_payload(qemu_irq irq)
+{
+    IRQMsg *msg = irq->msg;
+
+    return msg ? msg->payload : NULL;
+}
+
+void qemu_irq_fire_delivery_cb(qemu_irq irq, int level, int result)
+{
+    IRQMsg *msg = irq->msg;
+
+    if (msg && msg->delivery_cb) {
+        msg->delivery_cb(irq, msg->delivery_opaque, irq->n, level, result);
     }
 }
 
@@ -61,11 +80,27 @@ void qemu_free_irqs(qemu_irq *s)
     qemu_free(s);
 }
 
+static void qemu_notirq_delivery_cb(qemu_irq irq, void *opaque, int line,
+                                    int level, int result)
+{
+    qemu_irq orig_irq = opaque;
+
+    qemu_irq_fire_delivery_cb(orig_irq, !level, result);
+}
+
 static void qemu_notirq(qemu_irq irq, void *opaque, int line, int level)
 {
     struct IRQState *inv_irq = opaque;
+    IRQMsg msg;
 
+    if (irq->msg) {
+        msg.delivery_cb = qemu_notirq_delivery_cb;
+        msg.delivery_opaque = irq;
+        msg.payload = irq->msg->payload;
+        inv_irq->msg = &msg;
+    }
     inv_irq->handler(inv_irq, inv_irq->opaque, inv_irq->n, !level);
+    inv_irq->msg = NULL;
 }
 
 qemu_irq qemu_irq_invert(qemu_irq irq)
diff --git a/hw/irq.h b/hw/irq.h
index d0f83e3..01f96af 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,26 +3,62 @@
 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
+#define QEMU_IRQ_DELIVERED      0
+#define QEMU_IRQ_COALESCED      (-1)
+#define QEMU_IRQ_MASKED         (-2)
+
+typedef void (*qemu_irq_delivery_cb)(qemu_irq irq, void *opaque, int n,
+                                     int level, int result);
 typedef void (*qemu_irq_handler)(qemu_irq irq, void *opaque, int n, int level);
 
-void qemu_set_irq(qemu_irq irq, int level);
+typedef struct IRQMsg {
+    qemu_irq_delivery_cb delivery_cb;
+    void *delivery_opaque;
+    void *payload;
+} IRQMsg;
+
+void qemu_set_irq_msg(qemu_irq irq, int level, IRQMsg *msg);
+
+static inline void qemu_set_irq(qemu_irq irq, int level)
+{
+    qemu_set_irq_msg(irq, level, NULL);
+}
 
 static inline void qemu_irq_raise(qemu_irq irq)
 {
     qemu_set_irq(irq, 1);
 }
 
+static inline void qemu_irq_raise_msg(qemu_irq irq, IRQMsg *msg)
+{
+    qemu_set_irq_msg(irq, 1, msg);
+}
+
 static inline void qemu_irq_lower(qemu_irq irq)
 {
     qemu_set_irq(irq, 0);
 }
 
+static inline void qemu_irq_lower_msg(qemu_irq irq, IRQMsg *msg)
+{
+    qemu_set_irq_msg(irq, 0, msg);
+}
+
 static inline void qemu_irq_pulse(qemu_irq irq)
 {
     qemu_set_irq(irq, 1);
     qemu_set_irq(irq, 0);
 }
 
+static inline void qemu_irq_pulse_msg(qemu_irq irq, IRQMsg *msg)
+{
+    qemu_set_irq_msg(irq, 1, msg);
+    qemu_set_irq_msg(irq, 0, msg);
+}
+
+void qemu_irq_fire_delivery_cb(qemu_irq irq, int level, int result);
+void *qemu_irq_get_payload(qemu_irq irq);
+
 /* Returns an array of N IRQs.  */
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
 void qemu_free_irqs(qemu_irq *s);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (8 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs Jan Kiszka
@ 2010-06-06  8:10 ` Jan Kiszka
  2010-06-06  8:49   ` [Qemu-devel] " Blue Swirl
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET Jan Kiszka
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Make use of the new IRQ message and report delivery results from the
sink to the source. As a by-product, this also adds de-coalescing
support to the PIC.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/apic.c        |   64 +++++++++++++++++++----------------------
 hw/apic.h        |    9 ++----
 hw/i8259.c       |   16 ++++++++++-
 hw/ioapic.c      |   20 ++++++++++---
 hw/mc146818rtc.c |   83 ++++++++++++++++++++++++++++++++++-------------------
 hw/pc.c          |   29 ++++++++++++++++--
 6 files changed, 141 insertions(+), 80 deletions(-)

diff --git a/hw/apic.c b/hw/apic.c
index 7fbd79b..f9587d1 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -123,10 +123,8 @@ typedef struct APICState {
 static int apic_io_memory;
 static APICState *local_apics[MAX_APICS + 1];
 static int last_apic_idx = 0;
-static int apic_irq_delivered;
 
-
-static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
+static int apic_set_irq(APICState *s, int vector_num, int trigger_mode);
 static void apic_update_irq(APICState *s);
 static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
                                       uint8_t dest, uint8_t dest_mode);
@@ -239,12 +237,12 @@ void apic_deliver_pic_intr(CPUState *env, int level)
     }\
 }
 
-static void apic_bus_deliver(const uint32_t *deliver_bitmask,
-                             uint8_t delivery_mode,
-                             uint8_t vector_num, uint8_t polarity,
-                             uint8_t trigger_mode)
+static int apic_bus_deliver(const uint32_t *deliver_bitmask,
+                            uint8_t delivery_mode, uint8_t vector_num,
+                            uint8_t polarity, uint8_t trigger_mode)
 {
     APICState *apic_iter;
+    int ret;
 
     switch (delivery_mode) {
         case APIC_DM_LOWPRI:
@@ -261,11 +259,12 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
                 if (d >= 0) {
                     apic_iter = local_apics[d];
                     if (apic_iter) {
-                        apic_set_irq(apic_iter, vector_num, trigger_mode);
+                        return apic_set_irq(apic_iter, vector_num,
+                                            trigger_mode);
                     }
                 }
             }
-            return;
+            return QEMU_IRQ_MASKED;
 
         case APIC_DM_FIXED:
             break;
@@ -273,34 +272,42 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
         case APIC_DM_SMI:
             foreach_apic(apic_iter, deliver_bitmask,
                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
-            return;
+            return QEMU_IRQ_DELIVERED;
 
         case APIC_DM_NMI:
             foreach_apic(apic_iter, deliver_bitmask,
                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
-            return;
+            return QEMU_IRQ_DELIVERED;
 
         case APIC_DM_INIT:
             /* normal INIT IPI sent to processors */
             foreach_apic(apic_iter, deliver_bitmask,
                          cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
-            return;
+            return QEMU_IRQ_DELIVERED;
 
         case APIC_DM_EXTINT:
             /* handled in I/O APIC code */
             break;
 
         default:
-            return;
+            return QEMU_IRQ_MASKED;
     }
 
+    ret = QEMU_IRQ_MASKED;
     foreach_apic(apic_iter, deliver_bitmask,
-                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
+        if (ret == QEMU_IRQ_MASKED)
+            ret = QEMU_IRQ_COALESCED;
+        if (apic_set_irq(apic_iter, vector_num,
+                         trigger_mode) == QEMU_IRQ_DELIVERED) {
+            ret = QEMU_IRQ_DELIVERED;
+        }
+    );
+    return ret;
 }
 
-void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
-                      uint8_t delivery_mode, uint8_t vector_num,
-                      uint8_t polarity, uint8_t trigger_mode)
+int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
+                     uint8_t delivery_mode, uint8_t vector_num,
+                     uint8_t polarity, uint8_t trigger_mode)
 {
     uint32_t deliver_bitmask[MAX_APIC_WORDS];
 
@@ -308,8 +315,8 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
             " polarity %d trigger_mode %d\n", __func__, dest, dest_mode,
             delivery_mode, vector_num, polarity, trigger_mode);
     apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
-    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
-                     trigger_mode);
+    return apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num,
+                            polarity, trigger_mode);
 }
 
 void cpu_set_apic_base(CPUState *env, uint64_t val)
@@ -402,22 +409,10 @@ static void apic_update_irq(APICState *s)
     cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
 }
 
-void apic_reset_irq_delivered(void)
-{
-    DPRINTF_C("%s: old coalescing %d\n", __func__, apic_irq_delivered);
-    apic_irq_delivered = 0;
-}
-
-int apic_get_irq_delivered(void)
-{
-    DPRINTF_C("%s: returning coalescing %d\n", __func__, apic_irq_delivered);
-    return apic_irq_delivered;
-}
-
-static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
+static int apic_set_irq(APICState *s, int vector_num, int trigger_mode)
 {
-    apic_irq_delivered += !get_bit(s->irr, vector_num);
-    DPRINTF_C("%s: coalescing %d\n", __func__, apic_irq_delivered);
+    int ret = get_bit(s->irr, vector_num) ? QEMU_IRQ_COALESCED
+                                          : QEMU_IRQ_DELIVERED;
 
     set_bit(s->irr, vector_num);
     if (trigger_mode)
@@ -425,6 +420,7 @@ static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
     else
         reset_bit(s->tmr, vector_num);
     apic_update_irq(s);
+    return ret;
 }
 
 static void apic_eoi(APICState *s)
diff --git a/hw/apic.h b/hw/apic.h
index e1954f4..738d98a 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -2,17 +2,14 @@
 #define APIC_H
 
 typedef struct IOAPICState IOAPICState;
-void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
-                             uint8_t delivery_mode,
-                             uint8_t vector_num, uint8_t polarity,
-                             uint8_t trigger_mode);
+int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
+                     uint8_t delivery_mode, uint8_t vector_num,
+                     uint8_t polarity, uint8_t trigger_mode);
 int apic_init(CPUState *env);
 int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
-void apic_reset_irq_delivered(void);
-int apic_get_irq_delivered(void);
 
 int cpu_is_bsp(CPUState *env);
 
diff --git a/hw/i8259.c b/hw/i8259.c
index f743ee8..09150c4 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -189,6 +189,9 @@ int64_t irq_time[16];
 static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     PicState2 *s = opaque;
+    PicState *pic;
+    int result = QEMU_IRQ_DELIVERED;
+    int mask;
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
     if (level != irq_level[n]) {
@@ -205,8 +208,19 @@ static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
         irq_time[n] = qemu_get_clock(vm_clock);
     }
 #endif
-    pic_set_irq1(&s->pics[n >> 3], n & 7, level);
+    pic = &s->pics[n >> 3];
+    n &= 7;
+    mask = 1 << n;
+    if (level) {
+        if (pic->imr & mask) {
+            result = QEMU_IRQ_MASKED;
+        } else if (pic->irr & mask) {
+            result = QEMU_IRQ_COALESCED;
+        }
+    }
+    pic_set_irq1(pic, n, level);
     pic_update_irq(s);
+    qemu_irq_fire_delivery_cb(irq, level, result);
 }
 
 /* acknowledge interrupt 'irq' */
diff --git a/hw/ioapic.c b/hw/ioapic.c
index d818573..b54738f 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -58,7 +58,7 @@ struct IOAPICState {
     uint64_t ioredtbl[IOAPIC_NUM_PINS];
 };
 
-static void ioapic_service(IOAPICState *s)
+static int ioapic_service(IOAPICState *s)
 {
     uint8_t i;
     uint8_t trig_mode;
@@ -69,12 +69,16 @@ static void ioapic_service(IOAPICState *s)
     uint8_t dest;
     uint8_t dest_mode;
     uint8_t polarity;
+    int ret = QEMU_IRQ_MASKED;
 
     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
         mask = 1 << i;
         if (s->irr & mask) {
             entry = s->ioredtbl[i];
             if (!(entry & IOAPIC_LVT_MASKED)) {
+                if (ret == QEMU_IRQ_MASKED) {
+                    ret = QEMU_IRQ_COALESCED;
+                }
                 trig_mode = ((entry >> 15) & 1);
                 dest = entry >> 56;
                 dest_mode = (entry >> 11) & 1;
@@ -87,16 +91,21 @@ static void ioapic_service(IOAPICState *s)
                 else
                     vector = entry & 0xff;
 
-                apic_deliver_irq(dest, dest_mode, delivery_mode,
-                                 vector, polarity, trig_mode);
+                if (apic_deliver_irq(dest, dest_mode,
+                                     delivery_mode, vector, polarity,
+                                     trig_mode) == QEMU_IRQ_DELIVERED) {
+                    ret = QEMU_IRQ_DELIVERED;
+                }
             }
         }
     }
+    return ret;
 }
 
 static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
 {
     IOAPICState *s = opaque;
+    int result = QEMU_IRQ_MASKED;
 
     /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
      * to GSI 2.  GSI maps to ioapic 1-1.  This is not
@@ -114,7 +123,7 @@ static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
             /* level triggered */
             if (level) {
                 s->irr |= mask;
-                ioapic_service(s);
+                result = ioapic_service(s);
             } else {
                 s->irr &= ~mask;
             }
@@ -122,10 +131,11 @@ static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
             /* edge triggered */
             if (level) {
                 s->irr |= mask;
-                ioapic_service(s);
+                result = ioapic_service(s);
             }
         }
     }
+    qemu_irq_fire_delivery_cb(irq, level, result);
 }
 
 static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index c3e6a70..cbb98a4 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -25,7 +25,6 @@
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "pc.h"
-#include "apic.h"
 #include "isa.h"
 #include "hpet_emul.h"
 #include "mc146818rtc.h"
@@ -101,7 +100,7 @@ typedef struct RTCState {
     QEMUTimer *second_timer2;
 } RTCState;
 
-static void rtc_irq_raise(qemu_irq irq)
+static void rtc_irq_raise(RTCState *s, IRQMsg *msg)
 {
     /* When HPET is operating in legacy mode, RTC interrupts are disabled
      * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
@@ -109,9 +108,14 @@ static void rtc_irq_raise(qemu_irq irq)
      * be lowered in any case
      */
 #if defined TARGET_I386
-    if (!hpet_in_legacy_mode())
+    if (hpet_in_legacy_mode()) {
+        if (msg) {
+            msg->delivery_cb(s->irq, s, -1, -1, QEMU_IRQ_MASKED);
+        }
+        return;
+    }
 #endif
-        qemu_irq_raise(irq);
+    qemu_irq_raise_msg(s->irq, msg);
 }
 
 static void rtc_set_time(RTCState *s);
@@ -131,20 +135,41 @@ static void rtc_coalesced_timer_update(RTCState *s)
     }
 }
 
+static void rtc_periodic_delivery_cb(qemu_irq irq, void *opaque, int n,
+                                     int level, int result)
+{
+    RTCState *s = opaque;
+
+    if (result == QEMU_IRQ_COALESCED) {
+        s->irq_coalesced++;
+        rtc_coalesced_timer_update(s);
+        DPRINTF_C("cmos: coalesced irqs increased to %d\n", s->irq_coalesced);
+    }
+}
+
+static void rtc_reinject_delivery_cb(qemu_irq irq, void *opaque, int n,
+                                     int level, int result)
+{
+    RTCState *s = opaque;
+
+    if (result != QEMU_IRQ_COALESCED) {
+        s->irq_coalesced--;
+        DPRINTF_C("cmos: coalesced irqs decreased to %d\n", s->irq_coalesced);
+    }
+}
+
 static void rtc_coalesced_timer(void *opaque)
 {
     RTCState *s = opaque;
+    IRQMsg msg = {
+        .delivery_cb = rtc_reinject_delivery_cb,
+        .delivery_opaque = s,
+    };
 
     if (s->irq_coalesced != 0) {
-        apic_reset_irq_delivered();
         s->cmos_data[RTC_REG_C] |= 0xc0;
         DPRINTF_C("cmos: injecting from timer\n");
-        rtc_irq_raise(s->irq);
-        if (apic_get_irq_delivered()) {
-            s->irq_coalesced--;
-            DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
-                      s->irq_coalesced);
-        }
+        rtc_irq_raise(s, &msg);
     }
 
     rtc_coalesced_timer_update(s);
@@ -203,19 +228,18 @@ static void rtc_periodic_timer(void *opaque)
         s->cmos_data[RTC_REG_C] |= 0xc0;
 #ifdef TARGET_I386
         if(rtc_td_hack) {
-            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
-                s->irq_reinject_on_ack_count = 0;		
-            apic_reset_irq_delivered();
-            rtc_irq_raise(s->irq);
-            if (!apic_get_irq_delivered()) {
-                s->irq_coalesced++;
-                rtc_coalesced_timer_update(s);
-                DPRINTF_C("cmos: coalesced irqs increased to %d\n",
-                          s->irq_coalesced);
+            IRQMsg msg = {
+                .delivery_cb = rtc_periodic_delivery_cb,
+                .delivery_opaque = s,
+            };
+
+            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) {
+                s->irq_reinject_on_ack_count = 0;
             }
+            rtc_irq_raise(s, &msg);
         } else
 #endif
-        rtc_irq_raise(s->irq);
+        rtc_irq_raise(s, NULL);
     }
     if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
         /* Not square wave at all but we don't want 2048Hz interrupts!
@@ -444,7 +468,7 @@ static void rtc_update_second2(void *opaque)
              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
 
             s->cmos_data[RTC_REG_C] |= 0xa0;
-            rtc_irq_raise(s->irq);
+            rtc_irq_raise(s, NULL);
         }
     }
 
@@ -452,7 +476,7 @@ static void rtc_update_second2(void *opaque)
     s->cmos_data[RTC_REG_C] |= REG_C_UF;
     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
       s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-      rtc_irq_raise(s->irq);
+      rtc_irq_raise(s, NULL);
     }
 
     /* clear update in progress bit */
@@ -488,15 +512,14 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
 #ifdef TARGET_I386
             if(s->irq_coalesced &&
                     s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
+                IRQMsg msg = {
+                    .delivery_cb = rtc_reinject_delivery_cb,
+                    .delivery_opaque = s,
+                };
+
                 s->irq_reinject_on_ack_count++;
-                apic_reset_irq_delivered();
                 DPRINTF_C("cmos: injecting on ack\n");
-                qemu_irq_raise(s->irq);
-                if (apic_get_irq_delivered()) {
-                    s->irq_coalesced--;
-                    DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
-                              s->irq_coalesced);
-                }
+                qemu_irq_raise_msg(s->irq, &msg);
                 break;
             }
 #endif
diff --git a/hw/pc.c b/hw/pc.c
index 20057ca..6129e59 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -77,16 +77,37 @@ struct e820_table {
 
 static struct e820_table e820_table;
 
+static void isa_irq_delivery_cb(qemu_irq irq, void *opaque, int n, int level,
+                                int result)
+{
+    int *result_ptr = opaque;
+
+    *result_ptr = result;
+}
+
 void isa_irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
-    IsaIrqState *isa = (IsaIrqState *)opaque;
+    int result = QEMU_IRQ_MASKED;
+    IRQMsg msg = {
+        .delivery_cb = isa_irq_delivery_cb,
+    };
+    IsaIrqState *isa = opaque;
+    int ioapic_result;
 
     DPRINTF("isa_irqs: %s irq %d\n", level? "raise" : "lower", n);
     if (n < 16) {
-        qemu_set_irq(isa->i8259[n], level);
+        msg.delivery_opaque = &result;
+        qemu_set_irq_msg(isa->i8259[n], level, &msg);
+    }
+    if (isa->ioapic) {
+        msg.delivery_opaque = &ioapic_result;
+        qemu_set_irq_msg(isa->ioapic[n], level, &msg);
+        if (ioapic_result == QEMU_IRQ_DELIVERED ||
+            result == QEMU_IRQ_MASKED) {
+            result = ioapic_result;
+        }
     }
-    if (isa->ioapic)
-        qemu_set_irq(isa->ioapic[n], level);
+    qemu_irq_fire_delivery_cb(irq, level, result);
 };
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (9 preceding siblings ...)
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround Jan Kiszka
@ 2010-06-06  8:11 ` Jan Kiszka
  2010-06-06  8:53   ` [Qemu-devel] " Blue Swirl
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 12/16] hpet: Drop static state Jan Kiszka
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Allow the intercept the RTC IRQ for the HPET legacy mode. Then push
routing to IRQ8 completely into the HPET. This allows to turn
hpet_in_legacy_mode() into a private function. Furthermore, this stops
the RTC from clearing IRQ8 even if the HPET is in control.

This patch comes with a side effect: The RTC timers will no longer be
stoppend when there is no IRQ consumer, possibly causing a minor
performance degration. But as the guest may want to redirect the RTC to
the SCI in that mode, it should normally disable unused IRQ source
anyway.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c        |   42 +++++++++++++++++++++++++++++++++++-------
 hw/hpet_emul.h   |    4 ----
 hw/mc146818rtc.c |   54 +++++++++++++++---------------------------------------
 hw/mc146818rtc.h |    4 +++-
 hw/mips_jazz.c   |    2 +-
 hw/mips_malta.c  |    2 +-
 hw/mips_r4k.c    |    2 +-
 hw/pc.c          |   14 ++++++++------
 hw/ppc_prep.c    |    2 +-
 9 files changed, 65 insertions(+), 61 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 041dd84..d26cad5 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -30,6 +30,7 @@
 #include "qemu-timer.h"
 #include "hpet_emul.h"
 #include "sysbus.h"
+#include "mc146818rtc.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -58,6 +59,7 @@ typedef struct HPETState {
     SysBusDevice busdev;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    uint8_t rtc_irq_level;
     HPETTimer timer[HPET_NUM_TIMERS];
 
     /* Memory-mapped, software visible registers */
@@ -69,12 +71,9 @@ typedef struct HPETState {
 
 static HPETState *hpet_statep;
 
-uint32_t hpet_in_legacy_mode(void)
+static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
-    if (!hpet_statep) {
-        return 0;
-    }
-    return hpet_statep->config & HPET_CFG_LEGACY;
+    return s->config & HPET_CFG_LEGACY;
 }
 
 static uint32_t timer_int_route(struct HPETTimer *timer)
@@ -166,12 +165,12 @@ static void update_irq(struct HPETTimer *timer)
 {
     int route;
 
-    if (timer->tn <= 1 && hpet_in_legacy_mode()) {
+    if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
         /* if LegacyReplacementRoute bit is set, HPET specification requires
          * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
          * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
          */
-        route = (timer->tn == 0) ? 0 : 8;
+        route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
     } else {
         route = timer_int_route(timer);
     }
@@ -515,8 +514,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             /* i8254 and RTC are disabled when HPET is in legacy mode */
             if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
                 hpet_pit_disable();
+                qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
                 hpet_pit_enable();
+                qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
             }
             break;
         case HPET_CFG + 4:
@@ -607,6 +608,30 @@ static void hpet_reset(DeviceState *d)
     count = 1;
 }
 
+static void hpet_rtc_delivery_cb(qemu_irq irq, void *opaque, int n, int level,
+                                 int result)
+{
+    qemu_irq orig_irq = opaque;
+
+    qemu_irq_fire_delivery_cb(orig_irq, level, result);
+}
+
+static void hpet_handle_rtc_irq(qemu_irq irq, void *opaque, int n, int level)
+{
+    HPETState *s = FROM_SYSBUS(HPETState, opaque);
+    IRQMsg msg = {
+        .delivery_cb = hpet_rtc_delivery_cb,
+        .delivery_opaque = irq,
+    };
+
+    s->rtc_irq_level = level;
+    if (hpet_in_legacy_mode(s)) {
+        qemu_irq_fire_delivery_cb(irq, level, QEMU_IRQ_MASKED);
+    } else {
+        qemu_set_irq_msg(s->irqs[RTC_ISA_IRQ], level, &msg);
+    }
+}
+
 static int hpet_init(SysBusDevice *dev)
 {
     HPETState *s = FROM_SYSBUS(HPETState, dev);
@@ -625,6 +650,9 @@ static int hpet_init(SysBusDevice *dev)
         timer->state = s;
     }
 
+    isa_reserve_irq(RTC_ISA_IRQ);
+    qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
+
     /* HPET Area */
     iomemtype = cpu_register_io_memory(hpet_ram_read,
                                        hpet_ram_write, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 785f850..9c268cc 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -47,8 +47,4 @@
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
 
-#if defined TARGET_I386
-extern uint32_t hpet_in_legacy_mode(void);
-#endif
-
 #endif
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index cbb98a4..ac82810 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -26,7 +26,6 @@
 #include "sysemu.h"
 #include "pc.h"
 #include "isa.h"
-#include "hpet_emul.h"
 #include "mc146818rtc.h"
 
 //#define DEBUG_CMOS
@@ -100,24 +99,6 @@ typedef struct RTCState {
     QEMUTimer *second_timer2;
 } RTCState;
 
-static void rtc_irq_raise(RTCState *s, IRQMsg *msg)
-{
-    /* When HPET is operating in legacy mode, RTC interrupts are disabled
-     * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
-     * mode is established while interrupt is raised. We want it to
-     * be lowered in any case
-     */
-#if defined TARGET_I386
-    if (hpet_in_legacy_mode()) {
-        if (msg) {
-            msg->delivery_cb(s->irq, s, -1, -1, QEMU_IRQ_MASKED);
-        }
-        return;
-    }
-#endif
-    qemu_irq_raise_msg(s->irq, msg);
-}
-
 static void rtc_set_time(RTCState *s);
 static void rtc_copy_date(RTCState *s);
 
@@ -169,7 +150,7 @@ static void rtc_coalesced_timer(void *opaque)
     if (s->irq_coalesced != 0) {
         s->cmos_data[RTC_REG_C] |= 0xc0;
         DPRINTF_C("cmos: injecting from timer\n");
-        rtc_irq_raise(s, &msg);
+        qemu_irq_raise_msg(s->irq, &msg);
     }
 
     rtc_coalesced_timer_update(s);
@@ -180,19 +161,10 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
 {
     int period_code, period;
     int64_t cur_clock, next_irq_clock;
-    int enable_pie;
 
     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
-#if defined TARGET_I386
-    /* disable periodic timer if hpet is in legacy mode, since interrupts are
-     * disabled anyway.
-     */
-    enable_pie = !hpet_in_legacy_mode();
-#else
-    enable_pie = 1;
-#endif
     if (period_code != 0
-        && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
+        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
             || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
         if (period_code <= 2)
             period_code += 7;
@@ -236,10 +208,10 @@ static void rtc_periodic_timer(void *opaque)
             if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) {
                 s->irq_reinject_on_ack_count = 0;
             }
-            rtc_irq_raise(s, &msg);
+            qemu_irq_raise_msg(s->irq, &msg);
         } else
 #endif
-        rtc_irq_raise(s, NULL);
+        qemu_irq_raise(s->irq);
     }
     if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
         /* Not square wave at all but we don't want 2048Hz interrupts!
@@ -468,15 +440,15 @@ static void rtc_update_second2(void *opaque)
              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
 
             s->cmos_data[RTC_REG_C] |= 0xa0;
-            rtc_irq_raise(s, NULL);
+            qemu_irq_raise(s->irq);
         }
     }
 
     /* update ended interrupt */
     s->cmos_data[RTC_REG_C] |= REG_C_UF;
     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
-      s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
-      rtc_irq_raise(s, NULL);
+        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+        qemu_irq_raise(s->irq);
     }
 
     /* clear update in progress bit */
@@ -629,9 +601,6 @@ static int rtc_initfn(ISADevice *dev)
 {
     RTCState *s = DO_UPCAST(RTCState, dev, dev);
     int base = 0x70;
-    int isairq = 8;
-
-    isa_init_irq(dev, &s->irq, isairq);
 
     s->cmos_data[RTC_REG_A] = 0x26;
     s->cmos_data[RTC_REG_B] = 0x02;
@@ -661,13 +630,20 @@ static int rtc_initfn(ISADevice *dev)
     return 0;
 }
 
-ISADevice *rtc_init(int base_year)
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
 {
     ISADevice *dev;
+    RTCState *s;
 
     dev = isa_create("mc146818rtc");
+    s = DO_UPCAST(RTCState, dev, dev);
     qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
     qdev_init_nofail(&dev->qdev);
+    if (intercept_irq) {
+        s->irq = intercept_irq;
+    } else {
+        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
+    }
     return dev;
 }
 
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index 6f46a68..575968c 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -3,7 +3,9 @@
 
 #include "isa.h"
 
-ISADevice *rtc_init(int base_year);
+#define RTC_ISA_IRQ 8
+
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq);
 void rtc_set_memory(ISADevice *dev, int addr, int val);
 void rtc_set_date(ISADevice *dev, const struct tm *tm);
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index da1bf6e..5e52f59 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -259,7 +259,7 @@ void mips_jazz_init (ram_addr_t ram_size,
     fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
 
     /* Real time clock */
-    rtc_init(1980);
+    rtc_init(1980, NULL);
     s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
     cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);
 
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index bd86636..438e4e3 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -959,7 +959,7 @@ void mips_malta_init (ram_addr_t ram_size,
     /* Super I/O */
     isa_dev = isa_create_simple("i8042");
  
-    rtc_state = rtc_init(2000);
+    rtc_state = rtc_init(2000, NULL);
     serial_isa_init(0, serial_hds[0]);
     serial_isa_init(1, serial_hds[1]);
     if (parallel_hds[0])
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index f1fcfcd..5a96dea 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -267,7 +267,7 @@ void mips_r4k_init (ram_addr_t ram_size,
     isa_bus_new(NULL);
     isa_bus_irqs(i8259);
 
-    rtc_state = rtc_init(2000);
+    rtc_state = rtc_init(2000, NULL);
 
     /* Register 64 KB of ISA IO space at 0x14000000 */
 #ifdef TARGET_WORDS_BIGENDIAN
diff --git a/hw/pc.c b/hw/pc.c
index 6129e59..8460303 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -965,6 +965,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
     int i;
     DriveInfo *fd[MAX_FD];
     PITState *pit;
+    qemu_irq rtc_irq = NULL;
     qemu_irq *a20_line;
     ISADevice *i8042;
     qemu_irq *cpu_exit_irq;
@@ -973,19 +974,20 @@ void pc_basic_device_init(qemu_irq *isa_irq,
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    *rtc_state = rtc_init(2000);
-
-    qemu_register_boot_set(pc_boot_set, *rtc_state);
-
-    pit = pit_init(0x40, isa_reserve_irq(0));
-    pcspk_init(pit);
     if (!no_hpet) {
         DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
 
         for (i = 0; i < 24; i++) {
             sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
         }
+        rtc_irq = qdev_get_gpio_in(hpet, 0);
     }
+    *rtc_state = rtc_init(2000, rtc_irq);
+
+    qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+    pit = pit_init(0x40, isa_reserve_irq(0));
+    pcspk_init(pit);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index fd1ca86..f44a144 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -696,7 +696,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     pci_vga_init(pci_bus, 0, 0);
     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
     //    pit = pit_init(0x40, i8259[0]);
-    rtc_init(2000);
+    rtc_init(2000, NULL);
 
     if (serial_hds[0])
         serial_isa_init(0, serial_hds[0]);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 12/16] hpet: Drop static state
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (10 preceding siblings ...)
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET Jan Kiszka
@ 2010-06-06  8:11 ` Jan Kiszka
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 13/16] hpet: Add support for level-triggered interrupts Jan Kiszka
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Instead of keeping a static reference around, pass the state to
hpet_enabled and hpet_get_ticks. All callers now have it at hand. Will
once allow to instantiate the HPET more than a single time.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |   38 +++++++++++++++++---------------------
 1 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index d26cad5..3866061 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -69,8 +69,6 @@ typedef struct HPETState {
     uint64_t hpet_counter;      /* main counter */
 } HPETState;
 
-static HPETState *hpet_statep;
-
 static uint32_t hpet_in_legacy_mode(HPETState *s)
 {
     return s->config & HPET_CFG_LEGACY;
@@ -81,9 +79,9 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
     return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
-static uint32_t hpet_enabled(void)
+static uint32_t hpet_enabled(HPETState *s)
 {
-    return hpet_statep->config & HPET_CFG_ENABLE;
+    return s->config & HPET_CFG_ENABLE;
 }
 
 static uint32_t timer_is_periodic(HPETTimer *t)
@@ -133,9 +131,9 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
     return ((old & mask) && !(new & mask));
 }
 
-static uint64_t hpet_get_ticks(void)
+static uint64_t hpet_get_ticks(HPETState *s)
 {
-    return ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
+    return ns_to_ticks(qemu_get_clock(vm_clock) + s->hpet_offset);
 }
 
 /*
@@ -174,7 +172,7 @@ static void update_irq(struct HPETTimer *timer)
     } else {
         route = timer_int_route(timer);
     }
-    if (!timer_enabled(timer) || !hpet_enabled()) {
+    if (!timer_enabled(timer) || !hpet_enabled(timer->state)) {
         return;
     }
     qemu_irq_pulse(timer->state->irqs[route]);
@@ -185,7 +183,7 @@ static void hpet_pre_save(void *opaque)
     HPETState *s = opaque;
 
     /* save current counter value */
-    s->hpet_counter = hpet_get_ticks();
+    s->hpet_counter = hpet_get_ticks(s);
 }
 
 static int hpet_post_load(void *opaque, int version_id)
@@ -240,7 +238,7 @@ static void hpet_timer(void *opaque)
     uint64_t diff;
 
     uint64_t period = t->period;
-    uint64_t cur_tick = hpet_get_ticks();
+    uint64_t cur_tick = hpet_get_ticks(t->state);
 
     if (timer_is_periodic(t) && period != 0) {
         if (t->config & HPET_TN_32BIT) {
@@ -270,7 +268,7 @@ static void hpet_set_timer(HPETTimer *t)
 {
     uint64_t diff;
     uint32_t wrap_diff;  /* how many ticks until we wrap? */
-    uint64_t cur_tick = hpet_get_ticks();
+    uint64_t cur_tick = hpet_get_ticks(t->state);
 
     /* whenever new timer is being set up, make sure wrap_flag is 0 */
     t->wrap_flag = 0;
@@ -353,16 +351,16 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
             DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
             return 0;
         case HPET_COUNTER:
-            if (hpet_enabled()) {
-                cur_tick = hpet_get_ticks();
+            if (hpet_enabled(s)) {
+                cur_tick = hpet_get_ticks(s);
             } else {
                 cur_tick = s->hpet_counter;
             }
             DPRINTF("qemu: reading counter  = %" PRIx64 "\n", cur_tick);
             return cur_tick;
         case HPET_COUNTER + 4:
-            if (hpet_enabled()) {
-                cur_tick = hpet_get_ticks();
+            if (hpet_enabled(s)) {
+                cur_tick = hpet_get_ticks(s);
             } else {
                 cur_tick = s->hpet_counter;
             }
@@ -457,7 +455,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     (timer->period & 0xffffffff00000000ULL) | new_val;
             }
             timer->config &= ~HPET_TN_SETVAL;
-            if (hpet_enabled()) {
+            if (hpet_enabled(s)) {
                 hpet_set_timer(timer);
             }
             break;
@@ -476,7 +474,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     (timer->period & 0xffffffffULL) | new_val << 32;
                 }
                 timer->config &= ~HPET_TN_SETVAL;
-                if (hpet_enabled()) {
+                if (hpet_enabled(s)) {
                     hpet_set_timer(timer);
                 }
                 break;
@@ -506,7 +504,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 }
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
                 /* Halt main counter and disable interrupt generation. */
-                s->hpet_counter = hpet_get_ticks();
+                s->hpet_counter = hpet_get_ticks(s);
                 for (i = 0; i < HPET_NUM_TIMERS; i++) {
                     hpet_del_timer(&s->timer[i]);
                 }
@@ -527,7 +525,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             /* FIXME: need to handle level-triggered interrupts */
             break;
         case HPET_COUNTER:
-            if (hpet_enabled()) {
+            if (hpet_enabled(s)) {
                 DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
@@ -536,7 +534,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     value, s->hpet_counter);
             break;
         case HPET_COUNTER + 4:
-            if (hpet_enabled()) {
+            if (hpet_enabled(s)) {
                 DPRINTF("qemu: Writing counter while HPET enabled!\n");
             }
             s->hpet_counter =
@@ -638,8 +636,6 @@ static int hpet_init(SysBusDevice *dev)
     int i, iomemtype;
     HPETTimer *timer;
 
-    assert(!hpet_statep);
-    hpet_statep = s;
     for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 13/16] hpet: Add support for level-triggered interrupts
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (11 preceding siblings ...)
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 12/16] hpet: Drop static state Jan Kiszka
@ 2010-06-06  8:11 ` Jan Kiszka
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 14/16] vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8 Jan Kiszka
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

By implementing this feature we can also remove a nasty way to kill qemu
(by trying to enable level-triggered hpet interrupts).

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c |   32 ++++++++++++++++++++++----------
 1 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 3866061..eafdccb 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -159,8 +159,10 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
     }
 }
 
-static void update_irq(struct HPETTimer *timer)
+static void update_irq(struct HPETTimer *timer, int set)
 {
+    uint64_t mask;
+    HPETState *s;
     int route;
 
     if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
@@ -172,10 +174,18 @@ static void update_irq(struct HPETTimer *timer)
     } else {
         route = timer_int_route(timer);
     }
-    if (!timer_enabled(timer) || !hpet_enabled(timer->state)) {
-        return;
+    s = timer->state;
+    mask = 1 << timer->tn;
+    if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
+        s->isr &= ~mask;
+        qemu_irq_lower(s->irqs[route]);
+    } else if (timer->config & HPET_TN_TYPE_LEVEL) {
+        s->isr |= mask;
+        qemu_irq_raise(s->irqs[route]);
+    } else {
+        s->isr &= ~mask;
+        qemu_irq_pulse(s->irqs[route]);
     }
-    qemu_irq_pulse(timer->state->irqs[route]);
 }
 
 static void hpet_pre_save(void *opaque)
@@ -261,7 +271,7 @@ static void hpet_timer(void *opaque)
             t->wrap_flag = 0;
         }
     }
-    update_irq(t);
+    update_irq(t, 1);
 }
 
 static void hpet_set_timer(HPETTimer *t)
@@ -291,6 +301,7 @@ static void hpet_set_timer(HPETTimer *t)
 static void hpet_del_timer(HPETTimer *t)
 {
     qemu_del_timer(t->qemu_timer);
+    update_irq(t, 0);
 }
 
 #ifdef HPET_DEBUG
@@ -423,10 +434,6 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 timer->cmp = (uint32_t)timer->cmp;
                 timer->period = (uint32_t)timer->period;
             }
-            if (new_val & HPET_TN_TYPE_LEVEL) {
-                printf("qemu: level-triggered hpet not supported\n");
-                exit (-1);
-            }
             if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
                 hpet_set_timer(timer);
             } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
@@ -522,7 +529,12 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             DPRINTF("qemu: invalid HPET_CFG+4 write \n");
             break;
         case HPET_STATUS:
-            /* FIXME: need to handle level-triggered interrupts */
+            val = new_val & s->isr;
+            for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                if (val & (1 << i)) {
+                    update_irq(&s->timer[i], 0);
+                }
+            }
             break;
         case HPET_COUNTER:
             if (hpet_enabled(s)) {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 14/16] vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (12 preceding siblings ...)
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 13/16] hpet: Add support for level-triggered interrupts Jan Kiszka
@ 2010-06-06  8:11 ` Jan Kiszka
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 15/16] hpet: Make number of timers configurable Jan Kiszka
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Required for hpet.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hw.h |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index fc2d184..36be0be 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -474,6 +474,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
+#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint8_t),  \
+    .version_id = (_version),                                        \
+    .vmsd       = &(_vmsd),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_STRUCT|VMS_VARRAY_INT32,                       \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 15/16] hpet: Make number of timers configurable
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (13 preceding siblings ...)
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 14/16] vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8 Jan Kiszka
@ 2010-06-06  8:11 ` Jan Kiszka
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 16/16] hpet: Add MSI support Jan Kiszka
  2010-06-06  8:56 ` [Qemu-devel] Re: [PATCH 00/16] HPET cleanups, fixes, enhancements Blue Swirl
  16 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

One HPET block supports up to 32 timers. Allow to instantiate more than
the recommended and implemented minimum of 3. The number is configured
via the qdev property "timers". It is also saved/restored so that it
need not match between migration peers.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c      |   53 ++++++++++++++++++++++++++++++++++++++++-------------
 hw/hpet_emul.h |    6 +++++-
 2 files changed, 45 insertions(+), 14 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index eafdccb..7219967 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -60,7 +60,8 @@ typedef struct HPETState {
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     uint8_t rtc_irq_level;
-    HPETTimer timer[HPET_NUM_TIMERS];
+    uint8_t num_timers;
+    HPETTimer timer[HPET_MAX_TIMERS];
 
     /* Memory-mapped, software visible registers */
     uint64_t capability;        /* capabilities */
@@ -196,12 +197,25 @@ static void hpet_pre_save(void *opaque)
     s->hpet_counter = hpet_get_ticks(s);
 }
 
+static int hpet_pre_load(void *opaque)
+{
+    HPETState *s = opaque;
+
+    /* version 1 only supports 3, later versions will load the actual value */
+    s->num_timers = HPET_MIN_TIMERS;
+    return 0;
+}
+
 static int hpet_post_load(void *opaque, int version_id)
 {
     HPETState *s = opaque;
 
     /* Recalculate the offset between the main counter and guest time */
     s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+
+    /* Push number of timers into capability returned via HPET_ID */
+    s->capability &= ~HPET_ID_NUM_TIM_MASK;
+    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
     return 0;
 }
 
@@ -224,17 +238,19 @@ static const VMStateDescription vmstate_hpet_timer = {
 
 static const VMStateDescription vmstate_hpet = {
     .name = "hpet",
-    .version_id = 1,
+    .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .pre_save = hpet_pre_save,
+    .pre_load = hpet_pre_load,
     .post_load = hpet_post_load,
     .fields      = (VMStateField []) {
         VMSTATE_UINT64(config, HPETState),
         VMSTATE_UINT64(isr, HPETState),
         VMSTATE_UINT64(hpet_counter, HPETState),
-        VMSTATE_STRUCT_ARRAY(timer, HPETState, HPET_NUM_TIMERS, 0,
-                             vmstate_hpet_timer, HPETTimer),
+        VMSTATE_UINT8_V(num_timers, HPETState, 2),
+        VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
+                                    vmstate_hpet_timer, HPETTimer),
         VMSTATE_END_OF_LIST()
     }
 };
@@ -330,7 +346,7 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
         uint8_t timer_id = (addr - 0x100) / 0x20;
         HPETTimer *timer = &s->timer[timer_id];
 
-        if (timer_id > HPET_NUM_TIMERS - 1) {
+        if (timer_id > s->num_timers) {
             DPRINTF("qemu: timer id out of range\n");
             return 0;
         }
@@ -421,7 +437,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
         HPETTimer *timer = &s->timer[timer_id];
 
         DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
-        if (timer_id > HPET_NUM_TIMERS - 1) {
+        if (timer_id > s->num_timers) {
             DPRINTF("qemu: timer id out of range\n");
             return;
         }
@@ -504,7 +520,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                 /* Enable main counter and interrupt generation. */
                 s->hpet_offset =
                     ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
-                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                for (i = 0; i < s->num_timers; i++) {
                     if ((&s->timer[i])->cmp != ~0ULL) {
                         hpet_set_timer(&s->timer[i]);
                     }
@@ -512,7 +528,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
                 /* Halt main counter and disable interrupt generation. */
                 s->hpet_counter = hpet_get_ticks(s);
-                for (i = 0; i < HPET_NUM_TIMERS; i++) {
+                for (i = 0; i < s->num_timers; i++) {
                     hpet_del_timer(&s->timer[i]);
                 }
             }
@@ -530,7 +546,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
             break;
         case HPET_STATUS:
             val = new_val & s->isr;
-            for (i = 0; i < HPET_NUM_TIMERS; i++) {
+            for (i = 0; i < s->num_timers; i++) {
                 if (val & (1 << i)) {
                     update_irq(&s->timer[i], 0);
                 }
@@ -589,7 +605,7 @@ static void hpet_reset(DeviceState *d)
     int i;
     static int count = 0;
 
-    for (i = 0; i < HPET_NUM_TIMERS; i++) {
+    for (i = 0; i < s->num_timers; i++) {
         HPETTimer *timer = &s->timer[i];
 
         hpet_del_timer(timer);
@@ -603,8 +619,9 @@ static void hpet_reset(DeviceState *d)
 
     s->hpet_counter = 0ULL;
     s->hpet_offset = 0ULL;
-    /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
-    s->capability = 0x8086a201ULL;
+    /* 64-bit main counter; LegacyReplacementRoute. */
+    s->capability = 0x8086a001ULL;
+    s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
     s->capability |= ((HPET_CLK_PERIOD) << 32);
     s->config = 0ULL;
     if (count > 0) {
@@ -651,7 +668,13 @@ static int hpet_init(SysBusDevice *dev)
     for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
         sysbus_init_irq(dev, &s->irqs[i]);
     }
-    for (i = 0; i < HPET_NUM_TIMERS; i++) {
+
+    if (s->num_timers < HPET_MIN_TIMERS) {
+        s->num_timers = HPET_MIN_TIMERS;
+    } else if (s->num_timers > HPET_MAX_TIMERS) {
+        s->num_timers = HPET_MAX_TIMERS;
+    }
+    for (i = 0; i < HPET_MAX_TIMERS; i++) {
         timer = &s->timer[i];
         timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
         timer->tn = i;
@@ -675,6 +698,10 @@ static SysBusDeviceInfo hpet_device_info = {
     .qdev.vmsd    = &vmstate_hpet,
     .qdev.reset   = hpet_reset,
     .init         = hpet_init,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+        DEFINE_PROP_END_OF_LIST(),
+    },
 };
 
 static void hpet_register_device(void)
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 9c268cc..e8b794c 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -17,7 +17,8 @@
 #define HPET_CLK_PERIOD         10000000ULL /* 10000000 femtoseconds == 10ns*/
 
 #define FS_PER_NS 1000000
-#define HPET_NUM_TIMERS 3
+#define HPET_MIN_TIMERS         3
+#define HPET_MAX_TIMERS         32
 
 #define HPET_NUM_IRQ_ROUTES     32
 
@@ -34,6 +35,9 @@
 #define HPET_TN_ROUTE   0x010
 #define HPET_CFG_WRITE_MASK  0x3
 
+#define HPET_ID_NUM_TIM_SHIFT   8
+#define HPET_ID_NUM_TIM_MASK    0x1f00
+
 #define HPET_TN_TYPE_LEVEL       0x002
 #define HPET_TN_ENABLE           0x004
 #define HPET_TN_PERIODIC         0x008
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH 16/16] hpet: Add MSI support
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (14 preceding siblings ...)
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 15/16] hpet: Make number of timers configurable Jan Kiszka
@ 2010-06-06  8:11 ` Jan Kiszka
  2010-06-11 21:31   ` Paul Brook
  2010-06-06  8:56 ` [Qemu-devel] Re: [PATCH 00/16] HPET cleanups, fixes, enhancements Blue Swirl
  16 siblings, 1 reply; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  8:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

This implements the HPET capability of routing IRQs to the front-side
bus, aka MSI support. This feature can be enabled via the qdev property
"msi" and is off by default.

Note that switching it on can cause guests (at least Linux) to use the
HPET as timer instead of the LAPIC. KVM users should recall that only
the latter is currently available as fast in-kernel model.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/apic.c      |    2 +-
 hw/apic.h      |    1 +
 hw/hpet.c      |   39 +++++++++++++++++++++++++++++++++++----
 hw/hpet_emul.h |    4 +++-
 4 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/hw/apic.c b/hw/apic.c
index f9587d1..f33d20a 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -776,7 +776,7 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static void apic_send_msi(target_phys_addr_t addr, uint32 data)
+void apic_send_msi(target_phys_addr_t addr, uint32 data)
 {
     uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
     uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
diff --git a/hw/apic.h b/hw/apic.h
index 738d98a..9c646f0 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -5,6 +5,7 @@ typedef struct IOAPICState IOAPICState;
 int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
                      uint8_t delivery_mode, uint8_t vector_num,
                      uint8_t polarity, uint8_t trigger_mode);
+void apic_send_msi(target_phys_addr_t addr, uint32 data);
 int apic_init(CPUState *env);
 int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
diff --git a/hw/hpet.c b/hw/hpet.c
index 7219967..490a804 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -31,6 +31,7 @@
 #include "hpet_emul.h"
 #include "sysbus.h"
 #include "mc146818rtc.h"
+#include "apic.h"
 
 //#define HPET_DEBUG
 #ifdef HPET_DEBUG
@@ -39,6 +40,8 @@
 #define DPRINTF(...)
 #endif
 
+#define HPET_MSI_SUPPORT        0
+
 struct HPETState;
 typedef struct HPETTimer {  /* timers */
     uint8_t tn;             /*timer number*/
@@ -47,7 +50,7 @@ typedef struct HPETTimer {  /* timers */
     /* Memory-mapped, software visible timer registers */
     uint64_t config;        /* configuration/cap */
     uint64_t cmp;           /* comparator */
-    uint64_t fsb;           /* FSB route, not supported now */
+    uint64_t fsb;           /* FSB route */
     /* Hidden register state */
     uint64_t period;        /* Last value written to comparator */
     uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
@@ -59,6 +62,7 @@ typedef struct HPETState {
     SysBusDevice busdev;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    uint32_t flags;
     uint8_t rtc_irq_level;
     uint8_t num_timers;
     HPETTimer timer[HPET_MAX_TIMERS];
@@ -80,6 +84,11 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
     return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
+static uint32_t timer_fsb_route(HPETTimer *t)
+{
+    return t->config & HPET_TN_FSB_ENABLE;
+}
+
 static uint32_t hpet_enabled(HPETState *s)
 {
     return s->config & HPET_CFG_ENABLE;
@@ -179,7 +188,11 @@ static void update_irq(struct HPETTimer *timer, int set)
     mask = 1 << timer->tn;
     if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
         s->isr &= ~mask;
-        qemu_irq_lower(s->irqs[route]);
+        if (!timer_fsb_route(timer)) {
+            qemu_irq_lower(s->irqs[route]);
+        }
+    } else if (timer_fsb_route(timer)) {
+        apic_send_msi(timer->fsb >> 32, timer->fsb & 0xffffffff);
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
         qemu_irq_raise(s->irqs[route]);
@@ -216,6 +229,12 @@ static int hpet_post_load(void *opaque, int version_id)
     /* Push number of timers into capability returned via HPET_ID */
     s->capability &= ~HPET_ID_NUM_TIM_MASK;
     s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+
+    /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
+    s->flags &= ~(1 << HPET_MSI_SUPPORT);
+    if (s->timer[0].config & HPET_TN_FSB_CAP) {
+        s->flags |= 1 << HPET_MSI_SUPPORT;
+    }
     return 0;
 }
 
@@ -361,6 +380,8 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
         case HPET_TN_CMP + 4:
             return timer->cmp >> 32;
         case HPET_TN_ROUTE:
+            return timer->fsb;
+        case HPET_TN_ROUTE + 4:
             return timer->fsb >> 32;
         default:
             DPRINTF("qemu: invalid hpet_ram_readl\n");
@@ -444,6 +465,9 @@ 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");
+            if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
+                update_irq(timer, 0);
+            }
             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) {
@@ -501,8 +525,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     hpet_set_timer(timer);
                 }
                 break;
+        case HPET_TN_ROUTE:
+            timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
+            break;
         case HPET_TN_ROUTE + 4:
-            DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+            timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
             break;
         default:
             DPRINTF("qemu: invalid hpet_ram_writel\n");
@@ -610,7 +637,10 @@ static void hpet_reset(DeviceState *d)
 
         hpet_del_timer(timer);
         timer->cmp = ~0ULL;
-        timer->config =  HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+        timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+        if (s->flags & (1 << HPET_MSI_SUPPORT)) {
+            timer->config |= HPET_TN_FSB_CAP;
+        }
         /* advertise availability of ioapic inti2 */
         timer->config |=  0x00000004ULL << 32;
         timer->period = 0ULL;
@@ -700,6 +730,7 @@ static SysBusDeviceInfo hpet_device_info = {
     .init         = hpet_init,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+        DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index e8b794c..d7bc102 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -46,7 +46,9 @@
 #define HPET_TN_SETVAL           0x040
 #define HPET_TN_32BIT            0x100
 #define HPET_TN_INT_ROUTE_MASK  0x3e00
-#define HPET_TN_CFG_WRITE_MASK  0x3f4e
+#define HPET_TN_FSB_ENABLE      0x4000
+#define HPET_TN_FSB_CAP         0x8000
+#define HPET_TN_CFG_WRITE_MASK  0x7f4e
 #define HPET_TN_INT_ROUTE_SHIFT      9
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] Re: [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround Jan Kiszka
@ 2010-06-06  8:49   ` Blue Swirl
  2010-06-06  9:06     ` Jan Kiszka
  0 siblings, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-06  8:49 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: Jan Kiszka, Paul Brook, qemu-devel, Gleb Natapov, Juan Quintela

On Sun, Jun 6, 2010 at 8:10 AM, Jan Kiszka <jan.kiszka@web.de> wrote:
> From: Jan Kiszka <jan.kiszka@siemens.com>
>
> Make use of the new IRQ message and report delivery results from the
> sink to the source. As a by-product, this also adds de-coalescing
> support to the PIC.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>  hw/apic.c        |   64 +++++++++++++++++++----------------------
>  hw/apic.h        |    9 ++----
>  hw/i8259.c       |   16 ++++++++++-
>  hw/ioapic.c      |   20 ++++++++++---
>  hw/mc146818rtc.c |   83 ++++++++++++++++++++++++++++++++++-------------------
>  hw/pc.c          |   29 ++++++++++++++++--
>  6 files changed, 141 insertions(+), 80 deletions(-)
>
> diff --git a/hw/apic.c b/hw/apic.c
> index 7fbd79b..f9587d1 100644
> --- a/hw/apic.c
> +++ b/hw/apic.c
> @@ -123,10 +123,8 @@ typedef struct APICState {
>  static int apic_io_memory;
>  static APICState *local_apics[MAX_APICS + 1];
>  static int last_apic_idx = 0;
> -static int apic_irq_delivered;
>
> -
> -static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
> +static int apic_set_irq(APICState *s, int vector_num, int trigger_mode);
>  static void apic_update_irq(APICState *s);
>  static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
>                                       uint8_t dest, uint8_t dest_mode);
> @@ -239,12 +237,12 @@ void apic_deliver_pic_intr(CPUState *env, int level)
>     }\
>  }
>
> -static void apic_bus_deliver(const uint32_t *deliver_bitmask,
> -                             uint8_t delivery_mode,
> -                             uint8_t vector_num, uint8_t polarity,
> -                             uint8_t trigger_mode)
> +static int apic_bus_deliver(const uint32_t *deliver_bitmask,
> +                            uint8_t delivery_mode, uint8_t vector_num,
> +                            uint8_t polarity, uint8_t trigger_mode)
>  {
>     APICState *apic_iter;
> +    int ret;
>
>     switch (delivery_mode) {
>         case APIC_DM_LOWPRI:
> @@ -261,11 +259,12 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
>                 if (d >= 0) {
>                     apic_iter = local_apics[d];
>                     if (apic_iter) {
> -                        apic_set_irq(apic_iter, vector_num, trigger_mode);
> +                        return apic_set_irq(apic_iter, vector_num,
> +                                            trigger_mode);
>                     }
>                 }
>             }
> -            return;
> +            return QEMU_IRQ_MASKED;
>
>         case APIC_DM_FIXED:
>             break;
> @@ -273,34 +272,42 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
>         case APIC_DM_SMI:
>             foreach_apic(apic_iter, deliver_bitmask,
>                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
> -            return;
> +            return QEMU_IRQ_DELIVERED;
>
>         case APIC_DM_NMI:
>             foreach_apic(apic_iter, deliver_bitmask,
>                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
> -            return;
> +            return QEMU_IRQ_DELIVERED;
>
>         case APIC_DM_INIT:
>             /* normal INIT IPI sent to processors */
>             foreach_apic(apic_iter, deliver_bitmask,
>                          cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
> -            return;
> +            return QEMU_IRQ_DELIVERED;
>
>         case APIC_DM_EXTINT:
>             /* handled in I/O APIC code */
>             break;
>
>         default:
> -            return;
> +            return QEMU_IRQ_MASKED;
>     }
>
> +    ret = QEMU_IRQ_MASKED;
>     foreach_apic(apic_iter, deliver_bitmask,
> -                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
> +        if (ret == QEMU_IRQ_MASKED)
> +            ret = QEMU_IRQ_COALESCED;
> +        if (apic_set_irq(apic_iter, vector_num,
> +                         trigger_mode) == QEMU_IRQ_DELIVERED) {
> +            ret = QEMU_IRQ_DELIVERED;
> +        }
> +    );
> +    return ret;
>  }
>
> -void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
> -                      uint8_t delivery_mode, uint8_t vector_num,
> -                      uint8_t polarity, uint8_t trigger_mode)
> +int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
> +                     uint8_t delivery_mode, uint8_t vector_num,
> +                     uint8_t polarity, uint8_t trigger_mode)
>  {
>     uint32_t deliver_bitmask[MAX_APIC_WORDS];
>
> @@ -308,8 +315,8 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
>             " polarity %d trigger_mode %d\n", __func__, dest, dest_mode,
>             delivery_mode, vector_num, polarity, trigger_mode);
>     apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
> -    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
> -                     trigger_mode);
> +    return apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num,
> +                            polarity, trigger_mode);
>  }
>
>  void cpu_set_apic_base(CPUState *env, uint64_t val)
> @@ -402,22 +409,10 @@ static void apic_update_irq(APICState *s)
>     cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
>  }
>
> -void apic_reset_irq_delivered(void)
> -{
> -    DPRINTF_C("%s: old coalescing %d\n", __func__, apic_irq_delivered);
> -    apic_irq_delivered = 0;
> -}
> -
> -int apic_get_irq_delivered(void)
> -{
> -    DPRINTF_C("%s: returning coalescing %d\n", __func__, apic_irq_delivered);
> -    return apic_irq_delivered;
> -}
> -
> -static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
> +static int apic_set_irq(APICState *s, int vector_num, int trigger_mode)
>  {
> -    apic_irq_delivered += !get_bit(s->irr, vector_num);
> -    DPRINTF_C("%s: coalescing %d\n", __func__, apic_irq_delivered);
> +    int ret = get_bit(s->irr, vector_num) ? QEMU_IRQ_COALESCED
> +                                          : QEMU_IRQ_DELIVERED;
>
>     set_bit(s->irr, vector_num);
>     if (trigger_mode)
> @@ -425,6 +420,7 @@ static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
>     else
>         reset_bit(s->tmr, vector_num);
>     apic_update_irq(s);
> +    return ret;
>  }
>
>  static void apic_eoi(APICState *s)
> diff --git a/hw/apic.h b/hw/apic.h
> index e1954f4..738d98a 100644
> --- a/hw/apic.h
> +++ b/hw/apic.h
> @@ -2,17 +2,14 @@
>  #define APIC_H
>
>  typedef struct IOAPICState IOAPICState;
> -void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
> -                             uint8_t delivery_mode,
> -                             uint8_t vector_num, uint8_t polarity,
> -                             uint8_t trigger_mode);
> +int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
> +                     uint8_t delivery_mode, uint8_t vector_num,
> +                     uint8_t polarity, uint8_t trigger_mode);
>  int apic_init(CPUState *env);
>  int apic_accept_pic_intr(CPUState *env);
>  void apic_deliver_pic_intr(CPUState *env, int level);
>  int apic_get_interrupt(CPUState *env);
>  qemu_irq *ioapic_init(void);
> -void apic_reset_irq_delivered(void);
> -int apic_get_irq_delivered(void);
>
>  int cpu_is_bsp(CPUState *env);
>
> diff --git a/hw/i8259.c b/hw/i8259.c
> index f743ee8..09150c4 100644
> --- a/hw/i8259.c
> +++ b/hw/i8259.c
> @@ -189,6 +189,9 @@ int64_t irq_time[16];
>  static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
>  {
>     PicState2 *s = opaque;
> +    PicState *pic;
> +    int result = QEMU_IRQ_DELIVERED;
> +    int mask;
>
>  #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
>     if (level != irq_level[n]) {
> @@ -205,8 +208,19 @@ static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
>         irq_time[n] = qemu_get_clock(vm_clock);
>     }
>  #endif
> -    pic_set_irq1(&s->pics[n >> 3], n & 7, level);
> +    pic = &s->pics[n >> 3];
> +    n &= 7;
> +    mask = 1 << n;
> +    if (level) {
> +        if (pic->imr & mask) {
> +            result = QEMU_IRQ_MASKED;
> +        } else if (pic->irr & mask) {
> +            result = QEMU_IRQ_COALESCED;
> +        }
> +    }
> +    pic_set_irq1(pic, n, level);
>     pic_update_irq(s);
> +    qemu_irq_fire_delivery_cb(irq, level, result);
>  }
>
>  /* acknowledge interrupt 'irq' */
> diff --git a/hw/ioapic.c b/hw/ioapic.c
> index d818573..b54738f 100644
> --- a/hw/ioapic.c
> +++ b/hw/ioapic.c
> @@ -58,7 +58,7 @@ struct IOAPICState {
>     uint64_t ioredtbl[IOAPIC_NUM_PINS];
>  };
>
> -static void ioapic_service(IOAPICState *s)
> +static int ioapic_service(IOAPICState *s)
>  {
>     uint8_t i;
>     uint8_t trig_mode;
> @@ -69,12 +69,16 @@ static void ioapic_service(IOAPICState *s)
>     uint8_t dest;
>     uint8_t dest_mode;
>     uint8_t polarity;
> +    int ret = QEMU_IRQ_MASKED;
>
>     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
>         mask = 1 << i;
>         if (s->irr & mask) {
>             entry = s->ioredtbl[i];
>             if (!(entry & IOAPIC_LVT_MASKED)) {
> +                if (ret == QEMU_IRQ_MASKED) {
> +                    ret = QEMU_IRQ_COALESCED;
> +                }
>                 trig_mode = ((entry >> 15) & 1);
>                 dest = entry >> 56;
>                 dest_mode = (entry >> 11) & 1;
> @@ -87,16 +91,21 @@ static void ioapic_service(IOAPICState *s)
>                 else
>                     vector = entry & 0xff;
>
> -                apic_deliver_irq(dest, dest_mode, delivery_mode,
> -                                 vector, polarity, trig_mode);
> +                if (apic_deliver_irq(dest, dest_mode,
> +                                     delivery_mode, vector, polarity,
> +                                     trig_mode) == QEMU_IRQ_DELIVERED) {
> +                    ret = QEMU_IRQ_DELIVERED;
> +                }
>             }
>         }
>     }
> +    return ret;
>  }
>
>  static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
>  {
>     IOAPICState *s = opaque;
> +    int result = QEMU_IRQ_MASKED;
>
>     /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
>      * to GSI 2.  GSI maps to ioapic 1-1.  This is not
> @@ -114,7 +123,7 @@ static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
>             /* level triggered */
>             if (level) {
>                 s->irr |= mask;
> -                ioapic_service(s);
> +                result = ioapic_service(s);
>             } else {
>                 s->irr &= ~mask;
>             }
> @@ -122,10 +131,11 @@ static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
>             /* edge triggered */
>             if (level) {
>                 s->irr |= mask;
> -                ioapic_service(s);
> +                result = ioapic_service(s);
>             }
>         }
>     }
> +    qemu_irq_fire_delivery_cb(irq, level, result);
>  }
>
>  static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
> diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
> index c3e6a70..cbb98a4 100644
> --- a/hw/mc146818rtc.c
> +++ b/hw/mc146818rtc.c
> @@ -25,7 +25,6 @@
>  #include "qemu-timer.h"
>  #include "sysemu.h"
>  #include "pc.h"
> -#include "apic.h"
>  #include "isa.h"
>  #include "hpet_emul.h"
>  #include "mc146818rtc.h"
> @@ -101,7 +100,7 @@ typedef struct RTCState {
>     QEMUTimer *second_timer2;
>  } RTCState;
>
> -static void rtc_irq_raise(qemu_irq irq)
> +static void rtc_irq_raise(RTCState *s, IRQMsg *msg)
>  {
>     /* When HPET is operating in legacy mode, RTC interrupts are disabled
>      * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
> @@ -109,9 +108,14 @@ static void rtc_irq_raise(qemu_irq irq)
>      * be lowered in any case
>      */
>  #if defined TARGET_I386
> -    if (!hpet_in_legacy_mode())
> +    if (hpet_in_legacy_mode()) {
> +        if (msg) {
> +            msg->delivery_cb(s->irq, s, -1, -1, QEMU_IRQ_MASKED);

Shouldn't you use qemu_irq_fire_delivery_cb() here?

> +        }
> +        return;
> +    }
>  #endif
> -        qemu_irq_raise(irq);
> +    qemu_irq_raise_msg(s->irq, msg);
>  }
>
>  static void rtc_set_time(RTCState *s);
> @@ -131,20 +135,41 @@ static void rtc_coalesced_timer_update(RTCState *s)
>     }
>  }
>
> +static void rtc_periodic_delivery_cb(qemu_irq irq, void *opaque, int n,
> +                                     int level, int result)
> +{
> +    RTCState *s = opaque;
> +
> +    if (result == QEMU_IRQ_COALESCED) {
> +        s->irq_coalesced++;
> +        rtc_coalesced_timer_update(s);
> +        DPRINTF_C("cmos: coalesced irqs increased to %d\n", s->irq_coalesced);
> +    }
> +}
> +
> +static void rtc_reinject_delivery_cb(qemu_irq irq, void *opaque, int n,
> +                                     int level, int result)
> +{
> +    RTCState *s = opaque;
> +
> +    if (result != QEMU_IRQ_COALESCED) {
> +        s->irq_coalesced--;
> +        DPRINTF_C("cmos: coalesced irqs decreased to %d\n", s->irq_coalesced);
> +    }
> +}
> +
>  static void rtc_coalesced_timer(void *opaque)
>  {
>     RTCState *s = opaque;
> +    IRQMsg msg = {
> +        .delivery_cb = rtc_reinject_delivery_cb,
> +        .delivery_opaque = s,
> +    };
>
>     if (s->irq_coalesced != 0) {
> -        apic_reset_irq_delivered();
>         s->cmos_data[RTC_REG_C] |= 0xc0;
>         DPRINTF_C("cmos: injecting from timer\n");
> -        rtc_irq_raise(s->irq);
> -        if (apic_get_irq_delivered()) {
> -            s->irq_coalesced--;
> -            DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
> -                      s->irq_coalesced);
> -        }
> +        rtc_irq_raise(s, &msg);
>     }
>
>     rtc_coalesced_timer_update(s);
> @@ -203,19 +228,18 @@ static void rtc_periodic_timer(void *opaque)
>         s->cmos_data[RTC_REG_C] |= 0xc0;
>  #ifdef TARGET_I386
>         if(rtc_td_hack) {
> -            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
> -                s->irq_reinject_on_ack_count = 0;
> -            apic_reset_irq_delivered();
> -            rtc_irq_raise(s->irq);
> -            if (!apic_get_irq_delivered()) {
> -                s->irq_coalesced++;
> -                rtc_coalesced_timer_update(s);
> -                DPRINTF_C("cmos: coalesced irqs increased to %d\n",
> -                          s->irq_coalesced);
> +            IRQMsg msg = {
> +                .delivery_cb = rtc_periodic_delivery_cb,
> +                .delivery_opaque = s,
> +            };
> +
> +            if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) {
> +                s->irq_reinject_on_ack_count = 0;
>             }
> +            rtc_irq_raise(s, &msg);
>         } else
>  #endif
> -        rtc_irq_raise(s->irq);
> +        rtc_irq_raise(s, NULL);
>     }
>     if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
>         /* Not square wave at all but we don't want 2048Hz interrupts!
> @@ -444,7 +468,7 @@ static void rtc_update_second2(void *opaque)
>              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
>
>             s->cmos_data[RTC_REG_C] |= 0xa0;
> -            rtc_irq_raise(s->irq);
> +            rtc_irq_raise(s, NULL);
>         }
>     }
>
> @@ -452,7 +476,7 @@ static void rtc_update_second2(void *opaque)
>     s->cmos_data[RTC_REG_C] |= REG_C_UF;
>     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
>       s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> -      rtc_irq_raise(s->irq);
> +      rtc_irq_raise(s, NULL);
>     }
>
>     /* clear update in progress bit */
> @@ -488,15 +512,14 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
>  #ifdef TARGET_I386
>             if(s->irq_coalesced &&
>                     s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
> +                IRQMsg msg = {
> +                    .delivery_cb = rtc_reinject_delivery_cb,
> +                    .delivery_opaque = s,
> +                };
> +
>                 s->irq_reinject_on_ack_count++;
> -                apic_reset_irq_delivered();
>                 DPRINTF_C("cmos: injecting on ack\n");
> -                qemu_irq_raise(s->irq);
> -                if (apic_get_irq_delivered()) {
> -                    s->irq_coalesced--;
> -                    DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
> -                              s->irq_coalesced);
> -                }
> +                qemu_irq_raise_msg(s->irq, &msg);
>                 break;
>             }
>  #endif
> diff --git a/hw/pc.c b/hw/pc.c
> index 20057ca..6129e59 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -77,16 +77,37 @@ struct e820_table {
>
>  static struct e820_table e820_table;
>
> +static void isa_irq_delivery_cb(qemu_irq irq, void *opaque, int n, int level,
> +                                int result)
> +{
> +    int *result_ptr = opaque;
> +
> +    *result_ptr = result;
> +}
> +
>  void isa_irq_handler(qemu_irq irq, void *opaque, int n, int level)
>  {
> -    IsaIrqState *isa = (IsaIrqState *)opaque;
> +    int result = QEMU_IRQ_MASKED;
> +    IRQMsg msg = {
> +        .delivery_cb = isa_irq_delivery_cb,
> +    };
> +    IsaIrqState *isa = opaque;
> +    int ioapic_result;
>
>     DPRINTF("isa_irqs: %s irq %d\n", level? "raise" : "lower", n);
>     if (n < 16) {
> -        qemu_set_irq(isa->i8259[n], level);
> +        msg.delivery_opaque = &result;
> +        qemu_set_irq_msg(isa->i8259[n], level, &msg);
> +    }
> +    if (isa->ioapic) {
> +        msg.delivery_opaque = &ioapic_result;
> +        qemu_set_irq_msg(isa->ioapic[n], level, &msg);
> +        if (ioapic_result == QEMU_IRQ_DELIVERED ||
> +            result == QEMU_IRQ_MASKED) {
> +            result = ioapic_result;
> +        }
>     }
> -    if (isa->ioapic)
> -        qemu_set_irq(isa->ioapic[n], level);
> +    qemu_irq_fire_delivery_cb(irq, level, result);
>  };
>
>  static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
> --
> 1.6.0.2
>
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] Re: [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET Jan Kiszka
@ 2010-06-06  8:53   ` Blue Swirl
  2010-06-06  9:09     ` Jan Kiszka
  0 siblings, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-06  8:53 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: Jan Kiszka, Paul Brook, qemu-devel, Gleb Natapov, Juan Quintela

On Sun, Jun 6, 2010 at 8:11 AM, Jan Kiszka <jan.kiszka@web.de> wrote:
> From: Jan Kiszka <jan.kiszka@siemens.com>
>
> Allow the intercept the RTC IRQ for the HPET legacy mode. Then push
> routing to IRQ8 completely into the HPET. This allows to turn
> hpet_in_legacy_mode() into a private function. Furthermore, this stops
> the RTC from clearing IRQ8 even if the HPET is in control.
>
> This patch comes with a side effect: The RTC timers will no longer be
> stoppend when there is no IRQ consumer, possibly causing a minor
> performance degration. But as the guest may want to redirect the RTC to
> the SCI in that mode, it should normally disable unused IRQ source
> anyway.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>  hw/hpet.c        |   42 +++++++++++++++++++++++++++++++++++-------
>  hw/hpet_emul.h   |    4 ----
>  hw/mc146818rtc.c |   54 +++++++++++++++---------------------------------------
>  hw/mc146818rtc.h |    4 +++-
>  hw/mips_jazz.c   |    2 +-
>  hw/mips_malta.c  |    2 +-
>  hw/mips_r4k.c    |    2 +-
>  hw/pc.c          |   14 ++++++++------
>  hw/ppc_prep.c    |    2 +-
>  9 files changed, 65 insertions(+), 61 deletions(-)
>
> diff --git a/hw/hpet.c b/hw/hpet.c
> index 041dd84..d26cad5 100644
> --- a/hw/hpet.c
> +++ b/hw/hpet.c
> @@ -30,6 +30,7 @@
>  #include "qemu-timer.h"
>  #include "hpet_emul.h"
>  #include "sysbus.h"
> +#include "mc146818rtc.h"
>
>  //#define HPET_DEBUG
>  #ifdef HPET_DEBUG
> @@ -58,6 +59,7 @@ typedef struct HPETState {
>     SysBusDevice busdev;
>     uint64_t hpet_offset;
>     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
> +    uint8_t rtc_irq_level;
>     HPETTimer timer[HPET_NUM_TIMERS];
>
>     /* Memory-mapped, software visible registers */
> @@ -69,12 +71,9 @@ typedef struct HPETState {
>
>  static HPETState *hpet_statep;
>
> -uint32_t hpet_in_legacy_mode(void)
> +static uint32_t hpet_in_legacy_mode(HPETState *s)
>  {
> -    if (!hpet_statep) {
> -        return 0;
> -    }
> -    return hpet_statep->config & HPET_CFG_LEGACY;
> +    return s->config & HPET_CFG_LEGACY;
>  }
>
>  static uint32_t timer_int_route(struct HPETTimer *timer)
> @@ -166,12 +165,12 @@ static void update_irq(struct HPETTimer *timer)
>  {
>     int route;
>
> -    if (timer->tn <= 1 && hpet_in_legacy_mode()) {
> +    if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
>         /* if LegacyReplacementRoute bit is set, HPET specification requires
>          * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
>          * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
>          */
> -        route = (timer->tn == 0) ? 0 : 8;
> +        route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
>     } else {
>         route = timer_int_route(timer);
>     }
> @@ -515,8 +514,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
>             /* i8254 and RTC are disabled when HPET is in legacy mode */
>             if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
>                 hpet_pit_disable();
> +                qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
>             } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
>                 hpet_pit_enable();
> +                qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
>             }
>             break;
>         case HPET_CFG + 4:
> @@ -607,6 +608,30 @@ static void hpet_reset(DeviceState *d)
>     count = 1;
>  }
>
> +static void hpet_rtc_delivery_cb(qemu_irq irq, void *opaque, int n, int level,
> +                                 int result)
> +{
> +    qemu_irq orig_irq = opaque;
> +
> +    qemu_irq_fire_delivery_cb(orig_irq, level, result);
> +}
> +
> +static void hpet_handle_rtc_irq(qemu_irq irq, void *opaque, int n, int level)
> +{
> +    HPETState *s = FROM_SYSBUS(HPETState, opaque);
> +    IRQMsg msg = {
> +        .delivery_cb = hpet_rtc_delivery_cb,
> +        .delivery_opaque = irq,
> +    };
> +
> +    s->rtc_irq_level = level;
> +    if (hpet_in_legacy_mode(s)) {
> +        qemu_irq_fire_delivery_cb(irq, level, QEMU_IRQ_MASKED);
> +    } else {
> +        qemu_set_irq_msg(s->irqs[RTC_ISA_IRQ], level, &msg);

This is the problem with passing around stack allocated objects: after
this function finishes, s->irqs[RTC_ISA_IRQ].msg is a dangling pointer
to some stack space.

> +    }
> +}
> +
>  static int hpet_init(SysBusDevice *dev)
>  {
>     HPETState *s = FROM_SYSBUS(HPETState, dev);
> @@ -625,6 +650,9 @@ static int hpet_init(SysBusDevice *dev)
>         timer->state = s;
>     }
>
> +    isa_reserve_irq(RTC_ISA_IRQ);
> +    qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
> +
>     /* HPET Area */
>     iomemtype = cpu_register_io_memory(hpet_ram_read,
>                                        hpet_ram_write, s);
> diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
> index 785f850..9c268cc 100644
> --- a/hw/hpet_emul.h
> +++ b/hw/hpet_emul.h
> @@ -47,8 +47,4 @@
>  #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
>  #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
>
> -#if defined TARGET_I386
> -extern uint32_t hpet_in_legacy_mode(void);
> -#endif
> -
>  #endif
> diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
> index cbb98a4..ac82810 100644
> --- a/hw/mc146818rtc.c
> +++ b/hw/mc146818rtc.c
> @@ -26,7 +26,6 @@
>  #include "sysemu.h"
>  #include "pc.h"
>  #include "isa.h"
> -#include "hpet_emul.h"
>  #include "mc146818rtc.h"
>
>  //#define DEBUG_CMOS
> @@ -100,24 +99,6 @@ typedef struct RTCState {
>     QEMUTimer *second_timer2;
>  } RTCState;
>
> -static void rtc_irq_raise(RTCState *s, IRQMsg *msg)
> -{
> -    /* When HPET is operating in legacy mode, RTC interrupts are disabled
> -     * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
> -     * mode is established while interrupt is raised. We want it to
> -     * be lowered in any case
> -     */
> -#if defined TARGET_I386
> -    if (hpet_in_legacy_mode()) {
> -        if (msg) {
> -            msg->delivery_cb(s->irq, s, -1, -1, QEMU_IRQ_MASKED);
> -        }
> -        return;
> -    }
> -#endif
> -    qemu_irq_raise_msg(s->irq, msg);
> -}
> -
>  static void rtc_set_time(RTCState *s);
>  static void rtc_copy_date(RTCState *s);
>
> @@ -169,7 +150,7 @@ static void rtc_coalesced_timer(void *opaque)
>     if (s->irq_coalesced != 0) {
>         s->cmos_data[RTC_REG_C] |= 0xc0;
>         DPRINTF_C("cmos: injecting from timer\n");
> -        rtc_irq_raise(s, &msg);
> +        qemu_irq_raise_msg(s->irq, &msg);
>     }
>
>     rtc_coalesced_timer_update(s);
> @@ -180,19 +161,10 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
>  {
>     int period_code, period;
>     int64_t cur_clock, next_irq_clock;
> -    int enable_pie;
>
>     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
> -#if defined TARGET_I386
> -    /* disable periodic timer if hpet is in legacy mode, since interrupts are
> -     * disabled anyway.
> -     */
> -    enable_pie = !hpet_in_legacy_mode();
> -#else
> -    enable_pie = 1;
> -#endif
>     if (period_code != 0
> -        && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
> +        && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
>             || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
>         if (period_code <= 2)
>             period_code += 7;
> @@ -236,10 +208,10 @@ static void rtc_periodic_timer(void *opaque)
>             if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) {
>                 s->irq_reinject_on_ack_count = 0;
>             }
> -            rtc_irq_raise(s, &msg);
> +            qemu_irq_raise_msg(s->irq, &msg);
>         } else
>  #endif
> -        rtc_irq_raise(s, NULL);
> +        qemu_irq_raise(s->irq);
>     }
>     if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
>         /* Not square wave at all but we don't want 2048Hz interrupts!
> @@ -468,15 +440,15 @@ static void rtc_update_second2(void *opaque)
>              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
>
>             s->cmos_data[RTC_REG_C] |= 0xa0;
> -            rtc_irq_raise(s, NULL);
> +            qemu_irq_raise(s->irq);
>         }
>     }
>
>     /* update ended interrupt */
>     s->cmos_data[RTC_REG_C] |= REG_C_UF;
>     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
> -      s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> -      rtc_irq_raise(s, NULL);
> +        s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
> +        qemu_irq_raise(s->irq);
>     }
>
>     /* clear update in progress bit */
> @@ -629,9 +601,6 @@ static int rtc_initfn(ISADevice *dev)
>  {
>     RTCState *s = DO_UPCAST(RTCState, dev, dev);
>     int base = 0x70;
> -    int isairq = 8;
> -
> -    isa_init_irq(dev, &s->irq, isairq);
>
>     s->cmos_data[RTC_REG_A] = 0x26;
>     s->cmos_data[RTC_REG_B] = 0x02;
> @@ -661,13 +630,20 @@ static int rtc_initfn(ISADevice *dev)
>     return 0;
>  }
>
> -ISADevice *rtc_init(int base_year)
> +ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
>  {
>     ISADevice *dev;
> +    RTCState *s;
>
>     dev = isa_create("mc146818rtc");
> +    s = DO_UPCAST(RTCState, dev, dev);
>     qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
>     qdev_init_nofail(&dev->qdev);
> +    if (intercept_irq) {
> +        s->irq = intercept_irq;
> +    } else {
> +        isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
> +    }
>     return dev;
>  }
>
> diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
> index 6f46a68..575968c 100644
> --- a/hw/mc146818rtc.h
> +++ b/hw/mc146818rtc.h
> @@ -3,7 +3,9 @@
>
>  #include "isa.h"
>
> -ISADevice *rtc_init(int base_year);
> +#define RTC_ISA_IRQ 8
> +
> +ISADevice *rtc_init(int base_year, qemu_irq intercept_irq);
>  void rtc_set_memory(ISADevice *dev, int addr, int val);
>  void rtc_set_date(ISADevice *dev, const struct tm *tm);
>
> diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
> index da1bf6e..5e52f59 100644
> --- a/hw/mips_jazz.c
> +++ b/hw/mips_jazz.c
> @@ -259,7 +259,7 @@ void mips_jazz_init (ram_addr_t ram_size,
>     fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
>
>     /* Real time clock */
> -    rtc_init(1980);
> +    rtc_init(1980, NULL);
>     s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
>     cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);
>
> diff --git a/hw/mips_malta.c b/hw/mips_malta.c
> index bd86636..438e4e3 100644
> --- a/hw/mips_malta.c
> +++ b/hw/mips_malta.c
> @@ -959,7 +959,7 @@ void mips_malta_init (ram_addr_t ram_size,
>     /* Super I/O */
>     isa_dev = isa_create_simple("i8042");
>
> -    rtc_state = rtc_init(2000);
> +    rtc_state = rtc_init(2000, NULL);
>     serial_isa_init(0, serial_hds[0]);
>     serial_isa_init(1, serial_hds[1]);
>     if (parallel_hds[0])
> diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
> index f1fcfcd..5a96dea 100644
> --- a/hw/mips_r4k.c
> +++ b/hw/mips_r4k.c
> @@ -267,7 +267,7 @@ void mips_r4k_init (ram_addr_t ram_size,
>     isa_bus_new(NULL);
>     isa_bus_irqs(i8259);
>
> -    rtc_state = rtc_init(2000);
> +    rtc_state = rtc_init(2000, NULL);
>
>     /* Register 64 KB of ISA IO space at 0x14000000 */
>  #ifdef TARGET_WORDS_BIGENDIAN
> diff --git a/hw/pc.c b/hw/pc.c
> index 6129e59..8460303 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -965,6 +965,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
>     int i;
>     DriveInfo *fd[MAX_FD];
>     PITState *pit;
> +    qemu_irq rtc_irq = NULL;
>     qemu_irq *a20_line;
>     ISADevice *i8042;
>     qemu_irq *cpu_exit_irq;
> @@ -973,19 +974,20 @@ void pc_basic_device_init(qemu_irq *isa_irq,
>
>     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
>
> -    *rtc_state = rtc_init(2000);
> -
> -    qemu_register_boot_set(pc_boot_set, *rtc_state);
> -
> -    pit = pit_init(0x40, isa_reserve_irq(0));
> -    pcspk_init(pit);
>     if (!no_hpet) {
>         DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
>
>         for (i = 0; i < 24; i++) {
>             sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
>         }
> +        rtc_irq = qdev_get_gpio_in(hpet, 0);
>     }
> +    *rtc_state = rtc_init(2000, rtc_irq);
> +
> +    qemu_register_boot_set(pc_boot_set, *rtc_state);
> +
> +    pit = pit_init(0x40, isa_reserve_irq(0));
> +    pcspk_init(pit);
>
>     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
>         if (serial_hds[i]) {
> diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
> index fd1ca86..f44a144 100644
> --- a/hw/ppc_prep.c
> +++ b/hw/ppc_prep.c
> @@ -696,7 +696,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
>     pci_vga_init(pci_bus, 0, 0);
>     //    openpic = openpic_init(0x00000000, 0xF0000000, 1);
>     //    pit = pit_init(0x40, i8259[0]);
> -    rtc_init(2000);
> +    rtc_init(2000, NULL);
>
>     if (serial_hds[0])
>         serial_isa_init(0, serial_hds[0]);
> --
> 1.6.0.2
>
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] Re: [PATCH 00/16] HPET cleanups, fixes, enhancements
  2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
                   ` (15 preceding siblings ...)
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 16/16] hpet: Add MSI support Jan Kiszka
@ 2010-06-06  8:56 ` Blue Swirl
  2010-06-06  9:12   ` Jan Kiszka
  16 siblings, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-06  8:56 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Paul Brook, qemu-devel, Gleb Natapov, Juan Quintela

On Sun, Jun 6, 2010 at 8:10 AM, Jan Kiszka <jan.kiszka@web.de> wrote:
> Second round, specifically adressing:
>  - IRQMsg framework to refactor existing de-coalescing code
>  - RTC IRQ output as GPIO pin (routed depening on HPET or -no-hpet)
>  - ISA reservation for RTC IRQ
>
> If discussion around IRQMsg and de-coalescing happens to continue, I
> would suggest to merge patches 1..7 as they are likely uncontroversial
> and also fix bugs.

Otherwise everything looks fine to me, but 10 and 11 had minor
problems. Nice work!

I'd suppose one possible cleanup could be to use the message payload
in place of apic_deliver_irq()?

> Jan Kiszka (16):
>  hpet: Catch out-of-bounds timer access
>  hpet: Coding style cleanups and some refactorings
>  hpet: Silence warning on write to running main counter
>  hpet: Move static timer field initialization
>  hpet: Convert to qdev
>  hpet: Start/stop timer when HPET_TN_ENABLE is modified
>  monitor/QMP: Drop info hpet / query-hpet
>  Pass IRQ object on handler invocation
>  Enable message delivery via IRQs
>  x86: Refactor RTC IRQ coalescing workaround
>  hpet/rtc: Rework RTC IRQ replacement by HPET
>  hpet: Drop static state
>  hpet: Add support for level-triggered interrupts
>  vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8
>  hpet: Make number of timers configurable
>  hpet: Add MSI support
>
>  QMP/vm-info             |    2 +-
>  hw/acpi_piix4.c         |    3 +-
>  hw/apic.c               |   66 +++---
>  hw/apic.h               |   11 +-
>  hw/arm11mpcore.c        |   12 +-
>  hw/arm_gic.c            |   18 +-
>  hw/arm_pic.c            |    6 +-
>  hw/arm_timer.c          |    4 +-
>  hw/bitbang_i2c.c        |    4 +-
>  hw/bt-hci-csr.c         |    2 +-
>  hw/cbus.c               |    6 +-
>  hw/cris_pic_cpu.c       |    4 +-
>  hw/esp.c                |    2 +-
>  hw/etraxfs_pic.c        |   16 +-
>  hw/fdc.c                |    2 +-
>  hw/heathrow_pic.c       |    3 +-
>  hw/hpet.c               |  595 ++++++++++++++++++++++++++++++-----------------
>  hw/hpet_emul.h          |   46 +---
>  hw/hw.h                 |   10 +
>  hw/i8259.c              |   28 ++-
>  hw/ide/cmd646.c         |    2 +-
>  hw/ide/microdrive.c     |    2 +-
>  hw/integratorcp.c       |   10 +-
>  hw/ioapic.c             |   22 ++-
>  hw/irq.c                |   48 ++++-
>  hw/irq.h                |   42 +++-
>  hw/lance.c              |    2 +-
>  hw/max7310.c            |    2 +-
>  hw/mc146818rtc.c        |  111 +++++-----
>  hw/mc146818rtc.h        |    4 +-
>  hw/mcf5206.c            |    6 +-
>  hw/mcf_intc.c           |   14 +-
>  hw/microblaze_pic_cpu.c |    5 +-
>  hw/mips_int.c           |   10 +-
>  hw/mips_jazz.c          |    4 +-
>  hw/mips_malta.c         |    4 +-
>  hw/mips_r4k.c           |    2 +-
>  hw/mst_fpga.c           |   10 +-
>  hw/musicpal.c           |   16 +-
>  hw/nseries.c            |    4 +-
>  hw/omap.h               |    2 +-
>  hw/omap1.c              |   34 ++--
>  hw/omap2.c              |    8 +-
>  hw/omap_dma.c           |    8 +-
>  hw/omap_mmc.c           |    2 +-
>  hw/openpic.c            |    6 +-
>  hw/palm.c               |    2 +-
>  hw/pc.c                 |   59 ++++--
>  hw/pc.h                 |    8 +-
>  hw/pci.c                |    4 +-
>  hw/pl061.c              |    4 +-
>  hw/pl190.c              |    6 +-
>  hw/ppc.c                |    8 +-
>  hw/ppc4xx_devs.c        |    2 +-
>  hw/ppc_prep.c           |    4 +-
>  hw/pxa2xx.c             |    2 +-
>  hw/pxa2xx_gpio.c        |    2 +-
>  hw/pxa2xx_pcmcia.c      |    3 +-
>  hw/pxa2xx_pic.c         |   10 +-
>  hw/r2d.c                |    2 +-
>  hw/rc4030.c             |    7 +-
>  hw/sbi.c                |    2 +-
>  hw/sh_intc.c            |    4 +-
>  hw/sh_intc.h            |    2 +-
>  hw/sharpsl.h            |    1 -
>  hw/slavio_intctl.c      |   16 +-
>  hw/slavio_misc.c        |    3 +-
>  hw/sparc32_dma.c        |    2 +-
>  hw/spitz.c              |   14 +-
>  hw/ssd0323.c            |    2 +-
>  hw/stellaris.c          |    6 +-
>  hw/sun4c_intctl.c       |    8 +-
>  hw/sun4m.c              |   14 +-
>  hw/sun4u.c              |   12 +-
>  hw/syborg_interrupt.c   |    8 +-
>  hw/tc6393xb.c           |    7 +-
>  hw/tosa.c               |    2 +-
>  hw/tusb6010.c           |    3 +-
>  hw/twl92230.c           |    5 +-
>  hw/versatilepb.c        |   10 +-
>  hw/xilinx_intc.c        |    8 +-
>  hw/zaurus.c             |    2 +-
>  monitor.c               |   22 --
>  qemu-monitor.hx         |   21 --
>  84 files changed, 874 insertions(+), 643 deletions(-)
>
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] Re: [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround
  2010-06-06  8:49   ` [Qemu-devel] " Blue Swirl
@ 2010-06-06  9:06     ` Jan Kiszka
  0 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  9:06 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Paul Brook, qemu-devel, Gleb Natapov, Juan Quintela

[-- Attachment #1: Type: text/plain, Size: 12764 bytes --]

Blue Swirl wrote:
> On Sun, Jun 6, 2010 at 8:10 AM, Jan Kiszka <jan.kiszka@web.de> wrote:
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>
>> Make use of the new IRQ message and report delivery results from the
>> sink to the source. As a by-product, this also adds de-coalescing
>> support to the PIC.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>  hw/apic.c        |   64 +++++++++++++++++++----------------------
>>  hw/apic.h        |    9 ++----
>>  hw/i8259.c       |   16 ++++++++++-
>>  hw/ioapic.c      |   20 ++++++++++---
>>  hw/mc146818rtc.c |   83 ++++++++++++++++++++++++++++++++++-------------------
>>  hw/pc.c          |   29 ++++++++++++++++--
>>  6 files changed, 141 insertions(+), 80 deletions(-)
>>
>> diff --git a/hw/apic.c b/hw/apic.c
>> index 7fbd79b..f9587d1 100644
>> --- a/hw/apic.c
>> +++ b/hw/apic.c
>> @@ -123,10 +123,8 @@ typedef struct APICState {
>>  static int apic_io_memory;
>>  static APICState *local_apics[MAX_APICS + 1];
>>  static int last_apic_idx = 0;
>> -static int apic_irq_delivered;
>>
>> -
>> -static void apic_set_irq(APICState *s, int vector_num, int trigger_mode);
>> +static int apic_set_irq(APICState *s, int vector_num, int trigger_mode);
>>  static void apic_update_irq(APICState *s);
>>  static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
>>                                       uint8_t dest, uint8_t dest_mode);
>> @@ -239,12 +237,12 @@ void apic_deliver_pic_intr(CPUState *env, int level)
>>     }\
>>  }
>>
>> -static void apic_bus_deliver(const uint32_t *deliver_bitmask,
>> -                             uint8_t delivery_mode,
>> -                             uint8_t vector_num, uint8_t polarity,
>> -                             uint8_t trigger_mode)
>> +static int apic_bus_deliver(const uint32_t *deliver_bitmask,
>> +                            uint8_t delivery_mode, uint8_t vector_num,
>> +                            uint8_t polarity, uint8_t trigger_mode)
>>  {
>>     APICState *apic_iter;
>> +    int ret;
>>
>>     switch (delivery_mode) {
>>         case APIC_DM_LOWPRI:
>> @@ -261,11 +259,12 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
>>                 if (d >= 0) {
>>                     apic_iter = local_apics[d];
>>                     if (apic_iter) {
>> -                        apic_set_irq(apic_iter, vector_num, trigger_mode);
>> +                        return apic_set_irq(apic_iter, vector_num,
>> +                                            trigger_mode);
>>                     }
>>                 }
>>             }
>> -            return;
>> +            return QEMU_IRQ_MASKED;
>>
>>         case APIC_DM_FIXED:
>>             break;
>> @@ -273,34 +272,42 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
>>         case APIC_DM_SMI:
>>             foreach_apic(apic_iter, deliver_bitmask,
>>                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) );
>> -            return;
>> +            return QEMU_IRQ_DELIVERED;
>>
>>         case APIC_DM_NMI:
>>             foreach_apic(apic_iter, deliver_bitmask,
>>                 cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) );
>> -            return;
>> +            return QEMU_IRQ_DELIVERED;
>>
>>         case APIC_DM_INIT:
>>             /* normal INIT IPI sent to processors */
>>             foreach_apic(apic_iter, deliver_bitmask,
>>                          cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_INIT) );
>> -            return;
>> +            return QEMU_IRQ_DELIVERED;
>>
>>         case APIC_DM_EXTINT:
>>             /* handled in I/O APIC code */
>>             break;
>>
>>         default:
>> -            return;
>> +            return QEMU_IRQ_MASKED;
>>     }
>>
>> +    ret = QEMU_IRQ_MASKED;
>>     foreach_apic(apic_iter, deliver_bitmask,
>> -                 apic_set_irq(apic_iter, vector_num, trigger_mode) );
>> +        if (ret == QEMU_IRQ_MASKED)
>> +            ret = QEMU_IRQ_COALESCED;
>> +        if (apic_set_irq(apic_iter, vector_num,
>> +                         trigger_mode) == QEMU_IRQ_DELIVERED) {
>> +            ret = QEMU_IRQ_DELIVERED;
>> +        }
>> +    );
>> +    return ret;
>>  }
>>
>> -void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
>> -                      uint8_t delivery_mode, uint8_t vector_num,
>> -                      uint8_t polarity, uint8_t trigger_mode)
>> +int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
>> +                     uint8_t delivery_mode, uint8_t vector_num,
>> +                     uint8_t polarity, uint8_t trigger_mode)
>>  {
>>     uint32_t deliver_bitmask[MAX_APIC_WORDS];
>>
>> @@ -308,8 +315,8 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
>>             " polarity %d trigger_mode %d\n", __func__, dest, dest_mode,
>>             delivery_mode, vector_num, polarity, trigger_mode);
>>     apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
>> -    apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
>> -                     trigger_mode);
>> +    return apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num,
>> +                            polarity, trigger_mode);
>>  }
>>
>>  void cpu_set_apic_base(CPUState *env, uint64_t val)
>> @@ -402,22 +409,10 @@ static void apic_update_irq(APICState *s)
>>     cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
>>  }
>>
>> -void apic_reset_irq_delivered(void)
>> -{
>> -    DPRINTF_C("%s: old coalescing %d\n", __func__, apic_irq_delivered);
>> -    apic_irq_delivered = 0;
>> -}
>> -
>> -int apic_get_irq_delivered(void)
>> -{
>> -    DPRINTF_C("%s: returning coalescing %d\n", __func__, apic_irq_delivered);
>> -    return apic_irq_delivered;
>> -}
>> -
>> -static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
>> +static int apic_set_irq(APICState *s, int vector_num, int trigger_mode)
>>  {
>> -    apic_irq_delivered += !get_bit(s->irr, vector_num);
>> -    DPRINTF_C("%s: coalescing %d\n", __func__, apic_irq_delivered);
>> +    int ret = get_bit(s->irr, vector_num) ? QEMU_IRQ_COALESCED
>> +                                          : QEMU_IRQ_DELIVERED;
>>
>>     set_bit(s->irr, vector_num);
>>     if (trigger_mode)
>> @@ -425,6 +420,7 @@ static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
>>     else
>>         reset_bit(s->tmr, vector_num);
>>     apic_update_irq(s);
>> +    return ret;
>>  }
>>
>>  static void apic_eoi(APICState *s)
>> diff --git a/hw/apic.h b/hw/apic.h
>> index e1954f4..738d98a 100644
>> --- a/hw/apic.h
>> +++ b/hw/apic.h
>> @@ -2,17 +2,14 @@
>>  #define APIC_H
>>
>>  typedef struct IOAPICState IOAPICState;
>> -void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
>> -                             uint8_t delivery_mode,
>> -                             uint8_t vector_num, uint8_t polarity,
>> -                             uint8_t trigger_mode);
>> +int apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
>> +                     uint8_t delivery_mode, uint8_t vector_num,
>> +                     uint8_t polarity, uint8_t trigger_mode);
>>  int apic_init(CPUState *env);
>>  int apic_accept_pic_intr(CPUState *env);
>>  void apic_deliver_pic_intr(CPUState *env, int level);
>>  int apic_get_interrupt(CPUState *env);
>>  qemu_irq *ioapic_init(void);
>> -void apic_reset_irq_delivered(void);
>> -int apic_get_irq_delivered(void);
>>
>>  int cpu_is_bsp(CPUState *env);
>>
>> diff --git a/hw/i8259.c b/hw/i8259.c
>> index f743ee8..09150c4 100644
>> --- a/hw/i8259.c
>> +++ b/hw/i8259.c
>> @@ -189,6 +189,9 @@ int64_t irq_time[16];
>>  static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
>>  {
>>     PicState2 *s = opaque;
>> +    PicState *pic;
>> +    int result = QEMU_IRQ_DELIVERED;
>> +    int mask;
>>
>>  #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
>>     if (level != irq_level[n]) {
>> @@ -205,8 +208,19 @@ static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
>>         irq_time[n] = qemu_get_clock(vm_clock);
>>     }
>>  #endif
>> -    pic_set_irq1(&s->pics[n >> 3], n & 7, level);
>> +    pic = &s->pics[n >> 3];
>> +    n &= 7;
>> +    mask = 1 << n;
>> +    if (level) {
>> +        if (pic->imr & mask) {
>> +            result = QEMU_IRQ_MASKED;
>> +        } else if (pic->irr & mask) {
>> +            result = QEMU_IRQ_COALESCED;
>> +        }
>> +    }
>> +    pic_set_irq1(pic, n, level);
>>     pic_update_irq(s);
>> +    qemu_irq_fire_delivery_cb(irq, level, result);
>>  }
>>
>>  /* acknowledge interrupt 'irq' */
>> diff --git a/hw/ioapic.c b/hw/ioapic.c
>> index d818573..b54738f 100644
>> --- a/hw/ioapic.c
>> +++ b/hw/ioapic.c
>> @@ -58,7 +58,7 @@ struct IOAPICState {
>>     uint64_t ioredtbl[IOAPIC_NUM_PINS];
>>  };
>>
>> -static void ioapic_service(IOAPICState *s)
>> +static int ioapic_service(IOAPICState *s)
>>  {
>>     uint8_t i;
>>     uint8_t trig_mode;
>> @@ -69,12 +69,16 @@ static void ioapic_service(IOAPICState *s)
>>     uint8_t dest;
>>     uint8_t dest_mode;
>>     uint8_t polarity;
>> +    int ret = QEMU_IRQ_MASKED;
>>
>>     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
>>         mask = 1 << i;
>>         if (s->irr & mask) {
>>             entry = s->ioredtbl[i];
>>             if (!(entry & IOAPIC_LVT_MASKED)) {
>> +                if (ret == QEMU_IRQ_MASKED) {
>> +                    ret = QEMU_IRQ_COALESCED;
>> +                }
>>                 trig_mode = ((entry >> 15) & 1);
>>                 dest = entry >> 56;
>>                 dest_mode = (entry >> 11) & 1;
>> @@ -87,16 +91,21 @@ static void ioapic_service(IOAPICState *s)
>>                 else
>>                     vector = entry & 0xff;
>>
>> -                apic_deliver_irq(dest, dest_mode, delivery_mode,
>> -                                 vector, polarity, trig_mode);
>> +                if (apic_deliver_irq(dest, dest_mode,
>> +                                     delivery_mode, vector, polarity,
>> +                                     trig_mode) == QEMU_IRQ_DELIVERED) {
>> +                    ret = QEMU_IRQ_DELIVERED;
>> +                }
>>             }
>>         }
>>     }
>> +    return ret;
>>  }
>>
>>  static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
>>  {
>>     IOAPICState *s = opaque;
>> +    int result = QEMU_IRQ_MASKED;
>>
>>     /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
>>      * to GSI 2.  GSI maps to ioapic 1-1.  This is not
>> @@ -114,7 +123,7 @@ static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
>>             /* level triggered */
>>             if (level) {
>>                 s->irr |= mask;
>> -                ioapic_service(s);
>> +                result = ioapic_service(s);
>>             } else {
>>                 s->irr &= ~mask;
>>             }
>> @@ -122,10 +131,11 @@ static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
>>             /* edge triggered */
>>             if (level) {
>>                 s->irr |= mask;
>> -                ioapic_service(s);
>> +                result = ioapic_service(s);
>>             }
>>         }
>>     }
>> +    qemu_irq_fire_delivery_cb(irq, level, result);
>>  }
>>
>>  static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
>> diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
>> index c3e6a70..cbb98a4 100644
>> --- a/hw/mc146818rtc.c
>> +++ b/hw/mc146818rtc.c
>> @@ -25,7 +25,6 @@
>>  #include "qemu-timer.h"
>>  #include "sysemu.h"
>>  #include "pc.h"
>> -#include "apic.h"
>>  #include "isa.h"
>>  #include "hpet_emul.h"
>>  #include "mc146818rtc.h"
>> @@ -101,7 +100,7 @@ typedef struct RTCState {
>>     QEMUTimer *second_timer2;
>>  } RTCState;
>>
>> -static void rtc_irq_raise(qemu_irq irq)
>> +static void rtc_irq_raise(RTCState *s, IRQMsg *msg)
>>  {
>>     /* When HPET is operating in legacy mode, RTC interrupts are disabled
>>      * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
>> @@ -109,9 +108,14 @@ static void rtc_irq_raise(qemu_irq irq)
>>      * be lowered in any case
>>      */
>>  #if defined TARGET_I386
>> -    if (!hpet_in_legacy_mode())
>> +    if (hpet_in_legacy_mode()) {
>> +        if (msg) {
>> +            msg->delivery_cb(s->irq, s, -1, -1, QEMU_IRQ_MASKED);
> 
> Shouldn't you use qemu_irq_fire_delivery_cb() here?

We didn't send msg, so it is not yet associated with s->irq at this
point. Moreover, this hunk is only temporarily, removed in patch 11 again.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] Re: [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET
  2010-06-06  8:53   ` [Qemu-devel] " Blue Swirl
@ 2010-06-06  9:09     ` Jan Kiszka
  0 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  9:09 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Paul Brook, qemu-devel, Gleb Natapov, Juan Quintela

[-- Attachment #1: Type: text/plain, Size: 4694 bytes --]

Blue Swirl wrote:
> On Sun, Jun 6, 2010 at 8:11 AM, Jan Kiszka <jan.kiszka@web.de> wrote:
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>
>> Allow the intercept the RTC IRQ for the HPET legacy mode. Then push
>> routing to IRQ8 completely into the HPET. This allows to turn
>> hpet_in_legacy_mode() into a private function. Furthermore, this stops
>> the RTC from clearing IRQ8 even if the HPET is in control.
>>
>> This patch comes with a side effect: The RTC timers will no longer be
>> stoppend when there is no IRQ consumer, possibly causing a minor
>> performance degration. But as the guest may want to redirect the RTC to
>> the SCI in that mode, it should normally disable unused IRQ source
>> anyway.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>  hw/hpet.c        |   42 +++++++++++++++++++++++++++++++++++-------
>>  hw/hpet_emul.h   |    4 ----
>>  hw/mc146818rtc.c |   54 +++++++++++++++---------------------------------------
>>  hw/mc146818rtc.h |    4 +++-
>>  hw/mips_jazz.c   |    2 +-
>>  hw/mips_malta.c  |    2 +-
>>  hw/mips_r4k.c    |    2 +-
>>  hw/pc.c          |   14 ++++++++------
>>  hw/ppc_prep.c    |    2 +-
>>  9 files changed, 65 insertions(+), 61 deletions(-)
>>
>> diff --git a/hw/hpet.c b/hw/hpet.c
>> index 041dd84..d26cad5 100644
>> --- a/hw/hpet.c
>> +++ b/hw/hpet.c
>> @@ -30,6 +30,7 @@
>>  #include "qemu-timer.h"
>>  #include "hpet_emul.h"
>>  #include "sysbus.h"
>> +#include "mc146818rtc.h"
>>
>>  //#define HPET_DEBUG
>>  #ifdef HPET_DEBUG
>> @@ -58,6 +59,7 @@ typedef struct HPETState {
>>     SysBusDevice busdev;
>>     uint64_t hpet_offset;
>>     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
>> +    uint8_t rtc_irq_level;
>>     HPETTimer timer[HPET_NUM_TIMERS];
>>
>>     /* Memory-mapped, software visible registers */
>> @@ -69,12 +71,9 @@ typedef struct HPETState {
>>
>>  static HPETState *hpet_statep;
>>
>> -uint32_t hpet_in_legacy_mode(void)
>> +static uint32_t hpet_in_legacy_mode(HPETState *s)
>>  {
>> -    if (!hpet_statep) {
>> -        return 0;
>> -    }
>> -    return hpet_statep->config & HPET_CFG_LEGACY;
>> +    return s->config & HPET_CFG_LEGACY;
>>  }
>>
>>  static uint32_t timer_int_route(struct HPETTimer *timer)
>> @@ -166,12 +165,12 @@ static void update_irq(struct HPETTimer *timer)
>>  {
>>     int route;
>>
>> -    if (timer->tn <= 1 && hpet_in_legacy_mode()) {
>> +    if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
>>         /* if LegacyReplacementRoute bit is set, HPET specification requires
>>          * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
>>          * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
>>          */
>> -        route = (timer->tn == 0) ? 0 : 8;
>> +        route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
>>     } else {
>>         route = timer_int_route(timer);
>>     }
>> @@ -515,8 +514,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
>>             /* i8254 and RTC are disabled when HPET is in legacy mode */
>>             if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
>>                 hpet_pit_disable();
>> +                qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
>>             } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
>>                 hpet_pit_enable();
>> +                qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
>>             }
>>             break;
>>         case HPET_CFG + 4:
>> @@ -607,6 +608,30 @@ static void hpet_reset(DeviceState *d)
>>     count = 1;
>>  }
>>
>> +static void hpet_rtc_delivery_cb(qemu_irq irq, void *opaque, int n, int level,
>> +                                 int result)
>> +{
>> +    qemu_irq orig_irq = opaque;
>> +
>> +    qemu_irq_fire_delivery_cb(orig_irq, level, result);
>> +}
>> +
>> +static void hpet_handle_rtc_irq(qemu_irq irq, void *opaque, int n, int level)
>> +{
>> +    HPETState *s = FROM_SYSBUS(HPETState, opaque);
>> +    IRQMsg msg = {
>> +        .delivery_cb = hpet_rtc_delivery_cb,
>> +        .delivery_opaque = irq,
>> +    };
>> +
>> +    s->rtc_irq_level = level;
>> +    if (hpet_in_legacy_mode(s)) {
>> +        qemu_irq_fire_delivery_cb(irq, level, QEMU_IRQ_MASKED);
>> +    } else {
>> +        qemu_set_irq_msg(s->irqs[RTC_ISA_IRQ], level, &msg);
> 
> This is the problem with passing around stack allocated objects: after
> this function finishes, s->irqs[RTC_ISA_IRQ].msg is a dangling pointer
> to some stack space.

s->irqs[RTC_ISA_IRQ].msg is NULL when qemu_set_irq_msg returned, msg
itself will not "leak" out of the qemu_irq subsystem.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] Re: [PATCH 00/16] HPET cleanups, fixes, enhancements
  2010-06-06  8:56 ` [Qemu-devel] Re: [PATCH 00/16] HPET cleanups, fixes, enhancements Blue Swirl
@ 2010-06-06  9:12   ` Jan Kiszka
  0 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-06  9:12 UTC (permalink / raw)
  To: Blue Swirl; +Cc: Paul Brook, qemu-devel, Gleb Natapov, Juan Quintela

[-- Attachment #1: Type: text/plain, Size: 1003 bytes --]

Blue Swirl wrote:
> On Sun, Jun 6, 2010 at 8:10 AM, Jan Kiszka <jan.kiszka@web.de> wrote:
>> Second round, specifically adressing:
>>  - IRQMsg framework to refactor existing de-coalescing code
>>  - RTC IRQ output as GPIO pin (routed depening on HPET or -no-hpet)
>>  - ISA reservation for RTC IRQ
>>
>> If discussion around IRQMsg and de-coalescing happens to continue, I
>> would suggest to merge patches 1..7 as they are likely uncontroversial
>> and also fix bugs.
> 
> Otherwise everything looks fine to me, but 10 and 11 had minor
> problems. Nice work!

Thanks for the quick feedback!

> 
> I'd suppose one possible cleanup could be to use the message payload
> in place of apic_deliver_irq()?

Haven't looked into such things yet, the series is already long enough.
:) I could also imagine that we may avoid exporting the APIC MSI
functions for HPET use and instead provide a single MSI qemu_irq object,
pushing the vector information into the message payload.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 16/16] hpet: Add MSI support
  2010-06-06  8:11 ` [Qemu-devel] [PATCH 16/16] hpet: Add MSI support Jan Kiszka
@ 2010-06-11 21:31   ` Paul Brook
  2010-06-12 10:23     ` [Qemu-devel] [PATCH v3 " Jan Kiszka
  0 siblings, 1 reply; 44+ messages in thread
From: Paul Brook @ 2010-06-11 21:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Jan Kiszka, Gleb Natapov, Juan Quintela

> +    } else if (timer_fsb_route(timer)) {
> +        apic_send_msi(timer->fsb >> 32, timer->fsb & 0xffffffff);

This should use a regular memory write, like the PCI MSI-X code does.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH v3 16/16] hpet: Add MSI support
  2010-06-11 21:31   ` Paul Brook
@ 2010-06-12 10:23     ` Jan Kiszka
  0 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-12 10:23 UTC (permalink / raw)
  To: Paul Brook
  Cc: blue Swirl, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

Paul Brook wrote:
>> +    } else if (timer_fsb_route(timer)) {
>> +        apic_send_msi(timer->fsb >> 32, timer->fsb & 0xffffffff);
> 
> This should use a regular memory write, like the PCI MSI-X code does.
> 

Indeed, here we go:

---------->

From: Jan Kiszka <jan.kiszka@siemens.com>

This implements the HPET capability of routing IRQs to the front-side
bus, aka MSI support. This feature can be enabled via the qdev property
"msi" and is off by default.

Note that switching it on can cause guests (at least Linux) to use the
HPET as timer instead of the LAPIC. KVM users should recall that only
the latter is currently available as fast in-kernel model.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 hw/hpet.c      |   38 ++++++++++++++++++++++++++++++++++----
 hw/hpet_emul.h |    4 +++-
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/hw/hpet.c b/hw/hpet.c
index 7219967..117c598 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -39,6 +39,8 @@
 #define DPRINTF(...)
 #endif
 
+#define HPET_MSI_SUPPORT        0
+
 struct HPETState;
 typedef struct HPETTimer {  /* timers */
     uint8_t tn;             /*timer number*/
@@ -47,7 +49,7 @@ typedef struct HPETTimer {  /* timers */
     /* Memory-mapped, software visible timer registers */
     uint64_t config;        /* configuration/cap */
     uint64_t cmp;           /* comparator */
-    uint64_t fsb;           /* FSB route, not supported now */
+    uint64_t fsb;           /* FSB route */
     /* Hidden register state */
     uint64_t period;        /* Last value written to comparator */
     uint8_t wrap_flag;      /* timer pop will indicate wrap for one-shot 32-bit
@@ -59,6 +61,7 @@ typedef struct HPETState {
     SysBusDevice busdev;
     uint64_t hpet_offset;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+    uint32_t flags;
     uint8_t rtc_irq_level;
     uint8_t num_timers;
     HPETTimer timer[HPET_MAX_TIMERS];
@@ -80,6 +83,11 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
     return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
 }
 
+static uint32_t timer_fsb_route(HPETTimer *t)
+{
+    return t->config & HPET_TN_FSB_ENABLE;
+}
+
 static uint32_t hpet_enabled(HPETState *s)
 {
     return s->config & HPET_CFG_ENABLE;
@@ -179,7 +187,11 @@ static void update_irq(struct HPETTimer *timer, int set)
     mask = 1 << timer->tn;
     if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
         s->isr &= ~mask;
-        qemu_irq_lower(s->irqs[route]);
+        if (!timer_fsb_route(timer)) {
+            qemu_irq_lower(s->irqs[route]);
+        }
+    } else if (timer_fsb_route(timer)) {
+        stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
         s->isr |= mask;
         qemu_irq_raise(s->irqs[route]);
@@ -216,6 +228,12 @@ static int hpet_post_load(void *opaque, int version_id)
     /* Push number of timers into capability returned via HPET_ID */
     s->capability &= ~HPET_ID_NUM_TIM_MASK;
     s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+
+    /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
+    s->flags &= ~(1 << HPET_MSI_SUPPORT);
+    if (s->timer[0].config & HPET_TN_FSB_CAP) {
+        s->flags |= 1 << HPET_MSI_SUPPORT;
+    }
     return 0;
 }
 
@@ -361,6 +379,8 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
         case HPET_TN_CMP + 4:
             return timer->cmp >> 32;
         case HPET_TN_ROUTE:
+            return timer->fsb;
+        case HPET_TN_ROUTE + 4:
             return timer->fsb >> 32;
         default:
             DPRINTF("qemu: invalid hpet_ram_readl\n");
@@ -444,6 +464,9 @@ 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");
+            if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
+                update_irq(timer, 0);
+            }
             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) {
@@ -501,8 +524,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
                     hpet_set_timer(timer);
                 }
                 break;
+        case HPET_TN_ROUTE:
+            timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
+            break;
         case HPET_TN_ROUTE + 4:
-            DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+            timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
             break;
         default:
             DPRINTF("qemu: invalid hpet_ram_writel\n");
@@ -610,7 +636,10 @@ static void hpet_reset(DeviceState *d)
 
         hpet_del_timer(timer);
         timer->cmp = ~0ULL;
-        timer->config =  HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+        timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+        if (s->flags & (1 << HPET_MSI_SUPPORT)) {
+            timer->config |= HPET_TN_FSB_CAP;
+        }
         /* advertise availability of ioapic inti2 */
         timer->config |=  0x00000004ULL << 32;
         timer->period = 0ULL;
@@ -700,6 +729,7 @@ static SysBusDeviceInfo hpet_device_info = {
     .init         = hpet_init,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+        DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index e8b794c..d7bc102 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -46,7 +46,9 @@
 #define HPET_TN_SETVAL           0x040
 #define HPET_TN_32BIT            0x100
 #define HPET_TN_INT_ROUTE_MASK  0x3e00
-#define HPET_TN_CFG_WRITE_MASK  0x3f4e
+#define HPET_TN_FSB_ENABLE      0x4000
+#define HPET_TN_FSB_CAP         0x8000
+#define HPET_TN_CFG_WRITE_MASK  0x7f4e
 #define HPET_TN_INT_ROUTE_SHIFT      9
 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32
 #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH v3 08/16] Pass IRQ object on handler invocation
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 08/16] Pass IRQ object on handler invocation Jan Kiszka
@ 2010-06-12 10:31   ` Jan Kiszka
  0 siblings, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-12 10:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: blue Swirl, Paul Brook, Gleb Natapov, Juan Quintela

From: Jan Kiszka <jan.kiszka@siemens.com>

Pass the qemu_irq object to its handler when delivering an event. This
enables the handler to invoke optional services that require an object
reference. Will be used for IRQs with attached messages.

There are a few direct handler calls. So far we simply pass NULL as IRQ
object. Once those handlers want to make use of the object, the direct
callers need to obtain and forward a proper reference.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

Just rebased against current head.

 hw/acpi_piix4.c         |    3 ++-
 hw/apic.h               |    1 -
 hw/arm11mpcore.c        |   12 ++++++------
 hw/arm_gic.c            |   18 +++++++++---------
 hw/arm_pic.c            |    6 +++---
 hw/arm_timer.c          |    4 ++--
 hw/bitbang_i2c.c        |    4 ++--
 hw/bt-hci-csr.c         |    2 +-
 hw/cbus.c               |    6 +++---
 hw/cris_pic_cpu.c       |    4 ++--
 hw/esp.c                |    2 +-
 hw/etraxfs_pic.c        |   16 ++++++++--------
 hw/fdc.c                |    2 +-
 hw/heathrow_pic.c       |    3 ++-
 hw/i8259.c              |   14 +++++++-------
 hw/ide/cmd646.c         |    2 +-
 hw/ide/microdrive.c     |    2 +-
 hw/integratorcp.c       |   10 +++++-----
 hw/ioapic.c             |    2 +-
 hw/irq.c                |   13 ++++++-------
 hw/irq.h                |    4 +---
 hw/lance.c              |    2 +-
 hw/max7310.c            |    2 +-
 hw/mcf5206.c            |    6 +++---
 hw/mcf_intc.c           |   14 ++++++++------
 hw/microblaze_pic_cpu.c |    5 +++--
 hw/mips_int.c           |   10 +++++-----
 hw/mips_jazz.c          |    2 +-
 hw/mips_malta.c         |    2 +-
 hw/mst_fpga.c           |   10 +++++-----
 hw/musicpal.c           |   16 +++++++++-------
 hw/nseries.c            |    4 ++--
 hw/omap.h               |    2 +-
 hw/omap1.c              |   34 ++++++++++++++++++----------------
 hw/omap2.c              |    8 +++++---
 hw/omap_dma.c           |    8 ++++----
 hw/omap_mmc.c           |    2 +-
 hw/openpic.c            |    6 +++---
 hw/palm.c               |    2 +-
 hw/pc.c                 |   15 ++++++++-------
 hw/pc.h                 |    8 +++-----
 hw/pci.c                |    4 ++--
 hw/pl061.c              |    4 ++--
 hw/pl190.c              |    6 +++---
 hw/ppc.c                |    8 ++++----
 hw/ppc4xx_devs.c        |    2 +-
 hw/ppc_prep.c           |    2 +-
 hw/pxa2xx.c             |    2 +-
 hw/pxa2xx_gpio.c        |    2 +-
 hw/pxa2xx_pcmcia.c      |    3 ++-
 hw/pxa2xx_pic.c         |   10 +++++-----
 hw/r2d.c                |    2 +-
 hw/rc4030.c             |    7 ++++---
 hw/sbi.c                |    2 +-
 hw/sh_intc.c            |    4 ++--
 hw/sh_intc.h            |    2 +-
 hw/sharpsl.h            |    1 -
 hw/slavio_intctl.c      |   16 ++++++++--------
 hw/slavio_misc.c        |    3 ++-
 hw/sparc32_dma.c        |    2 +-
 hw/spitz.c              |   14 ++++++++------
 hw/ssd0323.c            |    2 +-
 hw/stellaris.c          |    6 ++++--
 hw/sun4c_intctl.c       |    8 ++++----
 hw/sun4m.c              |   14 +++++++-------
 hw/sun4u.c              |   12 ++++++------
 hw/syborg_interrupt.c   |    8 ++++----
 hw/tc6393xb.c           |    7 ++++---
 hw/tosa.c               |    2 +-
 hw/tusb6010.c           |    3 ++-
 hw/twl92230.c           |    5 +++--
 hw/versatilepb.c        |   10 +++++-----
 hw/xilinx_intc.c        |    8 ++++----
 hw/zaurus.c             |    2 +-
 74 files changed, 243 insertions(+), 228 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0fce958..a2268b2 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -316,7 +316,8 @@ static void piix4_reset(void *opaque)
     }
 }
 
-static void piix4_powerdown(void *opaque, int irq, int power_failing)
+static void piix4_powerdown(qemu_irq irq, void *opaque, int n,
+                            int power_failing)
 {
     PIIX4PMState *s = opaque;
 
diff --git a/hw/apic.h b/hw/apic.h
index 132fcab..e1954f4 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -11,7 +11,6 @@ int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
-void ioapic_set_irq(void *opaque, int vector, int level);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 3bbd885..694e238 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -32,18 +32,18 @@ static const int mpcore_irq_map[32] = {
     -1, -1, -1, -1,  9,  3, -1, -1,
 };
 
-static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
+static void mpcore_rirq_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
     int i;
 
     for (i = 0; i < 4; i++) {
-        qemu_set_irq(s->rvic[i][irq], level);
+        qemu_set_irq(s->rvic[i][n], level);
     }
-    if (irq < 32) {
-        irq = mpcore_irq_map[irq];
-        if (irq >= 0) {
-            qemu_set_irq(s->cpuic[irq], level);
+    if (n < 32) {
+        n = mpcore_irq_map[n];
+        if (n >= 0) {
+            qemu_set_irq(s->cpuic[n], level);
         }
     }
 }
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index c4afc6a..90aeb09 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -161,22 +161,22 @@ gic_set_pending_private(gic_state *s, int cpu, int irq)
 }
 
 /* Process a change in an external IRQ input.  */
-static void gic_set_irq(void *opaque, int irq, int level)
+static void gic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     gic_state *s = (gic_state *)opaque;
     /* The first external input line is internal interrupt 32.  */
-    irq += 32;
-    if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
+    n += 32;
+    if (level == GIC_TEST_LEVEL(n, ALL_CPU_MASK)) {
         return;
-
+    }
     if (level) {
-        GIC_SET_LEVEL(irq, ALL_CPU_MASK);
-        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
-            DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
-            GIC_SET_PENDING(irq, GIC_TARGET(irq));
+        GIC_SET_LEVEL(n, ALL_CPU_MASK);
+        if (GIC_TEST_TRIGGER(n) || GIC_TEST_ENABLED(n)) {
+            DPRINTF("Set %d pending mask %x\n", n, GIC_TARGET(n));
+            GIC_SET_PENDING(n, GIC_TARGET(n));
         }
     } else {
-        GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
+        GIC_CLEAR_LEVEL(n, ALL_CPU_MASK);
     }
     gic_update(s);
 }
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index f44568c..d6f8acc 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -22,10 +22,10 @@ void irq_info(Monitor *mon)
 
 
 /* Input 0 is IRQ and input 1 is FIQ.  */
-static void arm_pic_cpu_handler(void *opaque, int irq, int level)
+static void arm_pic_cpu_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = (CPUState *)opaque;
-    switch (irq) {
+    switch (n) {
     case ARM_PIC_CPU_IRQ:
         if (level)
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
@@ -39,7 +39,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
             cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ);
         break;
     default:
-        hw_error("arm_pic_cpu_handler: Bad interrput line %d\n", irq);
+        hw_error("arm_pic_cpu_handler: Bad interrput line %d\n", n);
     }
 }
 
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9073ffc..074254a 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -191,11 +191,11 @@ typedef struct {
 } sp804_state;
 
 /* Merge the IRQs from the two component devices.  */
-static void sp804_set_irq(void *opaque, int irq, int level)
+static void sp804_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     sp804_state *s = (sp804_state *)opaque;
 
-    s->level[irq] = level;
+    s->level[n] = level;
     qemu_set_irq(s->irq, s->level[0] || s->level[1]);
 }
 
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 4ee99a1..d4708d2 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -186,11 +186,11 @@ typedef struct {
     qemu_irq out;
 } GPIOI2CState;
 
-static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
+static void bitbang_i2c_gpio_set(qemu_irq irq, void *opaque, int n, int level)
 {
     GPIOI2CState *s = opaque;
 
-    level = bitbang_i2c_set(s->bitbang, irq, level);
+    level = bitbang_i2c_set(s->bitbang, n, level);
     if (level != s->last_level) {
         s->last_level = level;
         qemu_set_irq(s->out, level);
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index 982577d..1d63a5d 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -406,7 +406,7 @@ static void csrhci_out_tick(void *opaque)
     csrhci_fifo_wake((struct csrhci_s *) opaque);
 }
 
-static void csrhci_pins(void *opaque, int line, int level)
+static void csrhci_pins(qemu_irq irq, void *opaque, int line, int level)
 {
     struct csrhci_s *s = (struct csrhci_s *) opaque;
     int state = s->pin_state;
diff --git a/hw/cbus.c b/hw/cbus.c
index 8ae24e0..fa01ec0 100644
--- a/hw/cbus.c
+++ b/hw/cbus.c
@@ -93,7 +93,7 @@ static void cbus_cycle(CBusPriv *s)
     }
 }
 
-static void cbus_clk(void *opaque, int line, int level)
+static void cbus_clk(qemu_irq irq, void *opaque, int line, int level)
 {
     CBusPriv *s = (CBusPriv *) opaque;
 
@@ -110,14 +110,14 @@ static void cbus_clk(void *opaque, int line, int level)
     s->clk = level;
 }
 
-static void cbus_dat(void *opaque, int line, int level)
+static void cbus_dat(qemu_irq irq, void *opaque, int line, int level)
 {
     CBusPriv *s = (CBusPriv *) opaque;
 
     s->dat = level;
 }
 
-static void cbus_sel(void *opaque, int line, int level)
+static void cbus_sel(qemu_irq irq, void *opaque, int line, int level)
 {
     CBusPriv *s = (CBusPriv *) opaque;
 
diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c
index a92d445..f85ac24 100644
--- a/hw/cris_pic_cpu.c
+++ b/hw/cris_pic_cpu.c
@@ -33,10 +33,10 @@ void pic_info(Monitor *mon)
 void irq_info(Monitor *mon)
 {}
 
-static void cris_pic_cpu_handler(void *opaque, int irq, int level)
+static void cris_pic_cpu_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = (CPUState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+    int type = n ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level)
         cpu_interrupt(env, type);
diff --git a/hw/esp.c b/hw/esp.c
index 7740879..cc4abbe 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -443,7 +443,7 @@ static void esp_soft_reset(DeviceState *d)
     esp_hard_reset(d);
 }
 
-static void parent_esp_reset(void *opaque, int irq, int level)
+static void parent_esp_reset(qemu_irq irq, void *opaque, int n, int level)
 {
     if (level) {
         esp_soft_reset(opaque);
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index b2c4859..c612316 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -123,16 +123,16 @@ static void nmi_handler(void *opaque, int irq, int level)
     qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
 }
 
-static void irq_handler(void *opaque, int irq, int level)
-{   
+static void irq_handler(qemu_irq irq, void *opaque, int n, int level)
+{
     struct etrax_pic *fs = (void *)opaque;
 
-    if (irq >= 30)
-        return nmi_handler(opaque, irq, level);
-
-    irq -= 1;
-    fs->regs[R_R_VECT] &= ~(1 << irq);
-    fs->regs[R_R_VECT] |= (!!level << irq);
+    if (n >= 30) {
+        return nmi_handler(opaque, n, level);
+    }
+    n -= 1;
+    fs->regs[R_R_VECT] &= ~(1 << n);
+    fs->regs[R_R_VECT] |= (!!level << n);
     pic_update(fs);
 }
 
diff --git a/hw/fdc.c b/hw/fdc.c
index 6306496..d884d33 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -716,7 +716,7 @@ static void fdctrl_external_reset_isa(DeviceState *d)
     fdctrl_reset(s, 0);
 }
 
-static void fdctrl_handle_tc(void *opaque, int irq, int level)
+static void fdctrl_handle_tc(qemu_irq irq, void *opaque, int n, int level)
 {
     //FDCtrl *s = opaque;
 
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index 5e27021..1492312 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -135,7 +135,8 @@ static CPUReadMemoryFunc * const pic_read[] = {
 };
 
 
-static void heathrow_pic_set_irq(void *opaque, int num, int level)
+static void heathrow_pic_set_irq(qemu_irq irq, void *opaque, int num,
+                                 int level)
 {
     HeathrowPICS *s = opaque;
     HeathrowPIC *pic;
diff --git a/hw/i8259.c b/hw/i8259.c
index a995280..f743ee8 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -186,26 +186,26 @@ void pic_update_irq(PicState2 *s)
 int64_t irq_time[16];
 #endif
 
-static void i8259_set_irq(void *opaque, int irq, int level)
+static void i8259_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     PicState2 *s = opaque;
 
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
-    if (level != irq_level[irq]) {
-        DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level);
-        irq_level[irq] = level;
+    if (level != irq_level[n]) {
+        DPRINTF("i8259_set_irq: irq=%d level=%d\n", n, level);
+        irq_level[n] = level;
 #ifdef DEBUG_IRQ_COUNT
 	if (level == 1)
-	    irq_count[irq]++;
+	    irq_count[n]++;
 #endif
     }
 #endif
 #ifdef DEBUG_IRQ_LATENCY
     if (level) {
-        irq_time[irq] = qemu_get_clock(vm_clock);
+        irq_time[n] = qemu_get_clock(vm_clock);
     }
 #endif
-    pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
+    pic_set_irq1(&s->pics[n >> 3], n & 7, level);
     pic_update_irq(s);
 }
 
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index cdcc9bf..8ca55ea 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -202,7 +202,7 @@ static void cmd646_update_irq(PCIIDEState *d)
 }
 
 /* the PCI irq level is the logical OR of the two channels */
-static void cmd646_set_irq(void *opaque, int channel, int level)
+static void cmd646_set_irq(qemu_irq irq, void *opaque, int channel, int level)
 {
     PCIIDEState *d = opaque;
     int irq_mask;
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index bfdb8c8..c852665 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -92,7 +92,7 @@ static inline void md_interrupt_update(MicroDriveState *s)
                     !(s->opt & OPT_SRESET));
 }
 
-static void md_set_irq(void *opaque, int irq, int level)
+static void md_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     MicroDriveState *s = opaque;
     if (level)
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index bee8298..db78f04 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -286,13 +286,13 @@ static void icp_pic_update(icp_pic_state *s)
     qemu_set_irq(s->parent_fiq, flags != 0);
 }
 
-static void icp_pic_set_irq(void *opaque, int irq, int level)
+static void icp_pic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     icp_pic_state *s = (icp_pic_state *)opaque;
     if (level)
-        s->level |= 1 << irq;
+        s->level |= 1 << n;
     else
-        s->level &= ~(1 << irq);
+        s->level &= ~(1 << n);
     icp_pic_update(s);
 }
 
@@ -338,11 +338,11 @@ static void icp_pic_write(void *opaque, target_phys_addr_t offset,
         break;
     case 4: /* INT_SOFTSET */
         if (value & 1)
-            icp_pic_set_irq(s, 0, 1);
+            icp_pic_set_irq(NULL, s, 0, 1);
         break;
     case 5: /* INT_SOFTCLR */
         if (value & 1)
-            icp_pic_set_irq(s, 0, 0);
+            icp_pic_set_irq(NULL, s, 0, 0);
         break;
     case 10: /* FRQ_ENABLESET */
         s->fiq_enabled |= value;
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 335da6e..d818573 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -94,7 +94,7 @@ static void ioapic_service(IOAPICState *s)
     }
 }
 
-void ioapic_set_irq(void *opaque, int vector, int level)
+static void ioapic_set_irq(qemu_irq irq, void *opaque, int vector, int level)
 {
     IOAPICState *s = opaque;
 
diff --git a/hw/irq.c b/hw/irq.c
index 7703f62..24fb09d 100644
--- a/hw/irq.c
+++ b/hw/irq.c
@@ -32,10 +32,9 @@ struct IRQState {
 
 void qemu_set_irq(qemu_irq irq, int level)
 {
-    if (!irq)
-        return;
-
-    irq->handler(irq->opaque, irq->n, level);
+    if (irq) {
+        irq->handler(irq, irq->opaque, irq->n, level);
+    }
 }
 
 qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n)
@@ -62,11 +61,11 @@ void qemu_free_irqs(qemu_irq *s)
     qemu_free(s);
 }
 
-static void qemu_notirq(void *opaque, int line, int level)
+static void qemu_notirq(qemu_irq irq, void *opaque, int line, int level)
 {
-    struct IRQState *irq = opaque;
+    struct IRQState *inv_irq = opaque;
 
-    irq->handler(irq->opaque, irq->n, !level);
+    inv_irq->handler(inv_irq, inv_irq->opaque, inv_irq->n, !level);
 }
 
 qemu_irq qemu_irq_invert(qemu_irq irq)
diff --git a/hw/irq.h b/hw/irq.h
index 5daae44..d0f83e3 100644
--- a/hw/irq.h
+++ b/hw/irq.h
@@ -3,9 +3,7 @@
 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
-/* FIXME: Rmove one of these.  */
-typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
-typedef void SetIRQFunc(void *opaque, int irq_num, int level);
+typedef void (*qemu_irq_handler)(qemu_irq irq, void *opaque, int n, int level);
 
 void qemu_set_irq(qemu_irq irq, int level);
 
diff --git a/hw/lance.c b/hw/lance.c
index b6b04dd..de9e9bd 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -48,7 +48,7 @@ typedef struct {
     PCNetState state;
 } SysBusPCNetState;
 
-static void parent_lance_reset(void *opaque, int irq, int level)
+static void parent_lance_reset(qemu_irq irq, void *opaque, int n, int level)
 {
     SysBusPCNetState *d = opaque;
     if (level)
diff --git a/hw/max7310.c b/hw/max7310.c
index c302eb6..dc0f8ea 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -161,7 +161,7 @@ static const VMStateDescription vmstate_max7310 = {
     }
 };
 
-static void max7310_gpio_set(void *opaque, int line, int level)
+static void max7310_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     MAX7310State *s = (MAX7310State *) opaque;
     if (line >= ARRAY_SIZE(s->handler) || line  < 0)
diff --git a/hw/mcf5206.c b/hw/mcf5206.c
index c107de8..eca6e63 100644
--- a/hw/mcf5206.c
+++ b/hw/mcf5206.c
@@ -226,13 +226,13 @@ static void m5206_mbar_update(m5206_mbar_state *s)
     m68k_set_irq_level(s->env, level, vector);
 }
 
-static void m5206_mbar_set_irq(void *opaque, int irq, int level)
+static void m5206_mbar_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     m5206_mbar_state *s = (m5206_mbar_state *)opaque;
     if (level) {
-        s->ipr |= 1 << irq;
+        s->ipr |= 1 << n;
     } else {
-        s->ipr &= ~(1 << irq);
+        s->ipr &= ~(1 << n);
     }
     m5206_mbar_update(s);
 }
diff --git a/hw/mcf_intc.c b/hw/mcf_intc.c
index f01bd32..620c10e 100644
--- a/hw/mcf_intc.c
+++ b/hw/mcf_intc.c
@@ -105,15 +105,17 @@ static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
     mcf_intc_update(s);
 }
 
-static void mcf_intc_set_irq(void *opaque, int irq, int level)
+static void mcf_intc_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     mcf_intc_state *s = (mcf_intc_state *)opaque;
-    if (irq >= 64)
+    if (n >= 64) {
         return;
-    if (level)
-        s->ipr |= 1ull << irq;
-    else
-        s->ipr &= ~(1ull << irq);
+    }
+    if (level) {
+        s->ipr |= 1ull << n;
+    } else {
+        s->ipr &= ~(1ull << n);
+    }
     mcf_intc_update(s);
 }
 
diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c
index 7c59382..200832d 100644
--- a/hw/microblaze_pic_cpu.c
+++ b/hw/microblaze_pic_cpu.c
@@ -32,10 +32,11 @@ void pic_info(Monitor *mon)
 void irq_info(Monitor *mon)
 {}
 
-static void microblaze_pic_cpu_handler(void *opaque, int irq, int level)
+static void microblaze_pic_cpu_handler(qemu_irq irq, void *opaque, int n,
+                                       int level)
 {
     CPUState *env = (CPUState *)opaque;
-    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+    int type = n ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
 
     if (level)
         cpu_interrupt(env, type);
diff --git a/hw/mips_int.c b/hw/mips_int.c
index c30954c..434b47a 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -40,17 +40,17 @@ void cpu_mips_update_irq(CPUState *env)
         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
-static void cpu_mips_irq_request(void *opaque, int irq, int level)
+static void cpu_mips_irq_request(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = (CPUState *)opaque;
 
-    if (irq < 0 || irq > 7)
+    if (n < 0 || n > 7) {
         return;
-
+    }
     if (level) {
-        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+        env->CP0_Cause |= 1 << (n + CP0Ca_IP);
     } else {
-        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+        env->CP0_Cause &= ~(1 << (n + CP0Ca_IP));
     }
     cpu_mips_update_irq(env);
 }
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index ead3a00..da1bf6e 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -114,7 +114,7 @@ static void audio_init(qemu_irq *pic)
 #define MAGNUM_BIOS_SIZE_MAX 0x7e000
 #define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index a8f9d15..bd86636 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -763,7 +763,7 @@ static void main_cpu_reset(void *opaque)
     }
 }
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 1b6cb77..6d5fc8f 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -61,17 +61,17 @@ mst_fpga_update_gpio(mst_irq_state *s)
 }
 
 static void
-mst_fpga_set_irq(void *opaque, int irq, int level)
+mst_fpga_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
 	mst_irq_state *s = (mst_irq_state *)opaque;
 
 	if (level)
-		s->prev_level |= 1u << irq;
+		s->prev_level |= 1u << n;
 	else
-		s->prev_level &= ~(1u << irq);
+		s->prev_level &= ~(1u << n);
 
-	if(s->intmskena & (1u << irq)) {
-		s->intsetclr = 1u << irq;
+	if (s->intmskena & (1u << n)) {
+		s->intsetclr = 1u << n;
 		qemu_set_irq(s->parent[0], level);
 	}
 }
diff --git a/hw/musicpal.c b/hw/musicpal.c
index d44c5a0..fa86180 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -519,11 +519,12 @@ static void lcd_invalidate(void *opaque)
 {
 }
 
-static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
+static void musicpal_lcd_gpio_brigthness_in(qemu_irq irq, void *opaque, int n,
+                                            int level)
 {
     musicpal_lcd_state *s = opaque;
-    s->brightness &= ~(1 << irq);
-    s->brightness |= level << irq;
+    s->brightness &= ~(1 << n);
+    s->brightness |= level << n;
 }
 
 static uint32_t musicpal_lcd_read(void *opaque, target_phys_addr_t offset)
@@ -652,14 +653,14 @@ static void mv88w8618_pic_update(mv88w8618_pic_state *s)
     qemu_set_irq(s->parent_irq, (s->level & s->enabled));
 }
 
-static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
+static void mv88w8618_pic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     mv88w8618_pic_state *s = opaque;
 
     if (level) {
-        s->level |= 1 << irq;
+        s->level |= 1 << n;
     } else {
-        s->level &= ~(1 << irq);
+        s->level &= ~(1 << n);
     }
     mv88w8618_pic_update(s);
 }
@@ -1165,7 +1166,8 @@ static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
     }
 }
 
-static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
+static void musicpal_gpio_pin_event(qemu_irq irq, void *opaque, int pin,
+                                    int level)
 {
     musicpal_gpio_state *s = opaque;
     uint32_t mask = 1 << pin;
diff --git a/hw/nseries.c b/hw/nseries.c
index 04a028d..21cbf6c 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -122,7 +122,7 @@ struct n800_s {
 
 #define N8X0_BD_ADDR			0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
 
-static void n800_mmc_cs_cb(void *opaque, int line, int level)
+static void n800_mmc_cs_cb(qemu_irq irq, void *opaque, int line, int level)
 {
     /* TODO: this seems to actually be connected to the menelaus, to
      * which also both MMC slots connect.  */
@@ -754,7 +754,7 @@ static void n8x0_uart_setup(struct n800_s *s)
     omap_uart_attach(s->cpu->uart[BT_UART], radio);
 }
 
-static void n8x0_usb_power_cb(void *opaque, int line, int level)
+static void n8x0_usb_power_cb(qemu_irq irq, void *opaque, int line, int level)
 {
     struct n800_s *s = opaque;
 
diff --git a/hw/omap.h b/hw/omap.h
index d305779..4e31860 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -979,7 +979,7 @@ uint32_t omap_badwidth_read32(void *opaque, target_phys_addr_t addr);
 void omap_badwidth_write32(void *opaque, target_phys_addr_t addr,
                 uint32_t value);
 
-void omap_mpu_wakeup(void *opaque, int irq, int req);
+void omap_mpu_wakeup(qemu_irq irq, void *opaque, int n, int req);
 
 # define OMAP_BAD_REG(paddr)		\
         fprintf(stderr, "%s: Bad register " OMAP_FMT_plx "\n",	\
diff --git a/hw/omap1.c b/hw/omap1.c
index 8649dbd..cf2191d 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -150,13 +150,13 @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
 #define INT_FALLING_EDGE	0
 #define INT_LOW_LEVEL		1
 
-static void omap_set_intr(void *opaque, int irq, int req)
+static void omap_set_intr(qemu_irq irq, void *opaque, int line, int req)
 {
     struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
     uint32_t rise;
 
-    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-    int n = irq & 31;
+    struct omap_intr_handler_bank_s *bank = &ih->bank[line >> 5];
+    int n = line & 31;
 
     if (req) {
         rise = ~bank->irqs & (1 << n);
@@ -177,13 +177,13 @@ static void omap_set_intr(void *opaque, int irq, int req)
 }
 
 /* Simplified version with no edge detection */
-static void omap_set_intr_noedge(void *opaque, int irq, int req)
+static void omap_set_intr_noedge(qemu_irq irq, void *opaque, int line, int req)
 {
     struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
     uint32_t rise;
 
-    struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
-    int n = irq & 31;
+    struct omap_intr_handler_bank_s *bank = &ih->bank[line >> 5];
+    int n = line & 31;
 
     if (req) {
         rise = ~bank->inputs & (1 << n);
@@ -358,7 +358,7 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr,
     case 0x9c:	/* ISR */
         for (i = 0; i < 32; i ++)
             if (value & (1 << i)) {
-                omap_set_intr(s, 32 * bank_no + i, 1);
+                omap_set_intr(NULL, s, 32 * bank_no + i, 1);
                 return;
             }
         return;
@@ -732,7 +732,7 @@ static void omap_timer_tick(void *opaque)
     omap_timer_update(timer);
 }
 
-static void omap_timer_clk_update(void *opaque, int line, int on)
+static void omap_timer_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
 
@@ -2556,7 +2556,7 @@ struct omap_mpuio_s {
     int clk;
 };
 
-static void omap_mpuio_set(void *opaque, int line, int level)
+static void omap_mpuio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
     uint16_t prev = s->inputs;
@@ -2747,7 +2747,7 @@ static void omap_mpuio_reset(struct omap_mpuio_s *s)
     s->clk = 1;
 }
 
-static void omap_mpuio_onoff(void *opaque, int line, int on)
+static void omap_mpuio_onoff(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
 
@@ -2819,7 +2819,7 @@ struct omap_gpio_s {
     uint16_t pins;
 };
 
-static void omap_gpio_set(void *opaque, int line, int level)
+static void omap_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
     uint16_t prev = s->inputs;
@@ -3222,7 +3222,7 @@ static void omap_pwl_reset(struct omap_mpu_state_s *s)
     omap_pwl_update(s);
 }
 
-static void omap_pwl_clk_update(void *opaque, int line, int on)
+static void omap_pwl_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
 
@@ -4274,7 +4274,8 @@ struct omap_mcbsp_s *omap_mcbsp_init(target_phys_addr_t base,
     return s;
 }
 
-static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
+static void omap_mcbsp_i2s_swallow(qemu_irq irq, void *opaque, int line,
+                                   int level)
 {
     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
 
@@ -4284,7 +4285,8 @@ static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
     }
 }
 
-static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
+static void omap_mcbsp_i2s_start(qemu_irq irq, void *opaque, int line,
+                                 int level)
 {
     struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
 
@@ -4421,7 +4423,7 @@ static CPUWriteMemoryFunc * const omap_lpg_writefn[] = {
     omap_badwidth_write8,
 };
 
-static void omap_lpg_clk_update(void *opaque, int line, int on)
+static void omap_lpg_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
 
@@ -4560,7 +4562,7 @@ static void omap_setup_dsp_mapping(const struct omap_map_s *map)
     }
 }
 
-void omap_mpu_wakeup(void *opaque, int irq, int req)
+void omap_mpu_wakeup(qemu_irq irq, void *opaque, int n, int req)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
 
diff --git a/hw/omap2.c b/hw/omap2.c
index bd1b35e..ec73775 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -190,7 +190,7 @@ static void omap_gp_timer_match(void *opaque)
     omap_gp_timer_intr(timer, GPT_MAT_IT);
 }
 
-static void omap_gp_timer_input(void *opaque, int line, int on)
+static void omap_gp_timer_input(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
     int trigger;
@@ -220,7 +220,8 @@ static void omap_gp_timer_input(void *opaque, int line, int on)
     }
 }
 
-static void omap_gp_timer_clk_update(void *opaque, int line, int on)
+static void omap_gp_timer_clk_update(qemu_irq irq, void *opaque, int line,
+                                     int on)
 {
     struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
 
@@ -625,7 +626,8 @@ static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line)
     omap_gpio_module_wake(s, line);
 }
 
-static void omap_gpio_module_set(void *opaque, int line, int level)
+static void omap_gpio_module_set(qemu_irq irq, void *opaque, int line,
+                                 int level)
 {
     struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 
diff --git a/hw/omap_dma.c b/hw/omap_dma.c
index 3e718ba..4006d81 100644
--- a/hw/omap_dma.c
+++ b/hw/omap_dma.c
@@ -1542,7 +1542,7 @@ static CPUWriteMemoryFunc * const omap_dma_writefn[] = {
     omap_badwidth_write16,
 };
 
-static void omap_dma_request(void *opaque, int drq, int req)
+static void omap_dma_request(qemu_irq irq, void *opaque, int drq, int req)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     /* The request pins are level triggered in QEMU.  */
@@ -1556,7 +1556,7 @@ static void omap_dma_request(void *opaque, int drq, int req)
 }
 
 /* XXX: this won't be needed once soc_dma knows about clocks.  */
-static void omap_dma_clk_update(void *opaque, int line, int on)
+static void omap_dma_clk_update(qemu_irq irq, void *opaque, int line, int on)
 {
     struct omap_dma_s *s = (struct omap_dma_s *) opaque;
     int i;
@@ -1656,7 +1656,7 @@ struct soc_dma_s *omap_dma_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_setcaps(s);
     omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
     omap_dma_reset(s->dma);
-    omap_dma_clk_update(s, 0, 1);
+    omap_dma_clk_update(NULL, s, 0, 1);
 
     iomemtype = cpu_register_io_memory(omap_dma_readfn,
                     omap_dma_writefn, s);
@@ -2063,7 +2063,7 @@ struct soc_dma_s *omap_dma4_init(target_phys_addr_t base, qemu_irq *irqs,
     omap_dma_setcaps(s);
     omap_clk_adduser(s->clk, qemu_allocate_irqs(omap_dma_clk_update, s, 1)[0]);
     omap_dma_reset(s->dma);
-    omap_dma_clk_update(s, 0, !!s->dma->freq);
+    omap_dma_clk_update(NULL, s, 0, !!s->dma->freq);
 
     iomemtype = cpu_register_io_memory(omap_dma4_readfn,
                     omap_dma4_writefn, s);
diff --git a/hw/omap_mmc.c b/hw/omap_mmc.c
index 15cbf06..ec8719e 100644
--- a/hw/omap_mmc.c
+++ b/hw/omap_mmc.c
@@ -552,7 +552,7 @@ static CPUWriteMemoryFunc * const omap_mmc_writefn[] = {
     omap_badwidth_write16,
 };
 
-static void omap_mmc_cover_cb(void *opaque, int line, int level)
+static void omap_mmc_cover_cb(qemu_irq irq, void *opaque, int line, int level)
 {
     struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
 
diff --git a/hw/openpic.c b/hw/openpic.c
index ac21993..74730ee 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -399,7 +399,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
     }
 }
 
-static void openpic_set_irq(void *opaque, int n_IRQ, int level)
+static void openpic_set_irq(qemu_irq irq, void *opaque, int n_IRQ, int level)
 {
     openpic_t *opp = opaque;
     IRQ_src_t *src;
@@ -832,8 +832,8 @@ static void openpic_cpu_write (void *opaque, target_phys_addr_t addr, uint32_t v
     case 0x70:
         idx = (addr - 0x40) >> 4;
         write_IRQreg(opp, opp->irq_ipi0 + idx, IRQ_IDE, val);
-        openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
-        openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
+        openpic_set_irq(NULL, opp, opp->irq_ipi0 + idx, 1);
+        openpic_set_irq(NULL, opp, opp->irq_ipi0 + idx, 0);
         break;
 #endif
     case 0x80: /* PCTP */
diff --git a/hw/palm.c b/hw/palm.c
index 8db133d..88448c2 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -131,7 +131,7 @@ static void palmte_button_event(void *opaque, int keycode)
                         !(keycode & 0x80));
 }
 
-static void palmte_onoff_gpios(void *opaque, int line, int level)
+static void palmte_onoff_gpios(qemu_irq irq, void *opaque, int line, int level)
 {
     switch (line) {
     case 0:
diff --git a/hw/pc.c b/hw/pc.c
index ae31e2e..20057ca 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -77,7 +77,7 @@ struct e820_table {
 
 static struct e820_table e820_table;
 
-void isa_irq_handler(void *opaque, int n, int level)
+void isa_irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     IsaIrqState *isa = (IsaIrqState *)opaque;
 
@@ -158,11 +158,11 @@ int cpu_get_pic_interrupt(CPUState *env)
     return intno;
 }
 
-static void pic_irq_request(void *opaque, int irq, int level)
+static void pic_irq_request(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = first_cpu;
 
-    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
+    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", n);
     if (env->apic_state) {
         while (env) {
             if (apic_accept_pic_intr(env))
@@ -378,7 +378,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     rtc_set_memory(s, 0x39, val);
 }
 
-static void handle_a20_line_change(void *opaque, int irq, int level)
+static void handle_a20_line_change(qemu_irq irq, void *opaque, int n,
+                                   int level)
 {
     CPUState *cpu = opaque;
 
@@ -750,7 +751,7 @@ int cpu_is_bsp(CPUState *env)
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
    BIOS will read it and start S3 resume at POST Entry */
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
+void pc_cmos_set_s3_resume(qemu_irq irq, void *opaque, int n, int level)
 {
     ISADevice *s = opaque;
 
@@ -759,7 +760,7 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
     }
 }
 
-void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
+void pc_acpi_smi_interrupt(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *s = opaque;
 
@@ -927,7 +928,7 @@ void pc_vga_init(PCIBus *pci_bus)
     }
 }
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/pc.h b/hw/pc.h
index 0e52933..82b902f 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -29,8 +29,6 @@ ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq
 
 typedef struct PicState2 PicState2;
 extern PicState2 *isa_pic;
-void pic_set_irq(int irq, int level);
-void pic_set_irq_new(void *opaque, int irq, int level);
 qemu_irq *i8259_init(qemu_irq parent_irq);
 int pic_read_irq(PicState2 *s);
 void pic_update_irq(PicState2 *s);
@@ -44,7 +42,7 @@ typedef struct isa_irq_state {
     qemu_irq *ioapic;
 } IsaIrqState;
 
-void isa_irq_handler(void *opaque, int n, int level);
+void isa_irq_handler(qemu_irq irq, void *opaque, int n, int level);
 
 /* i8254.c */
 
@@ -82,8 +80,8 @@ void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out);
 extern int fd_bootchk;
 
 void pc_register_ferr_irq(qemu_irq irq);
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
-void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
+void pc_cmos_set_s3_resume(qemu_irq irq, void *opaque, int n, int level);
+void pc_acpi_smi_interrupt(qemu_irq irq, void *opaque, int n, int level);
 
 void pc_cpus_init(const char *cpu_model);
 void pc_memory_init(ram_addr_t ram_size,
diff --git a/hw/pci.c b/hw/pci.c
index cbbd1dd..edca65a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -72,7 +72,7 @@ static struct BusInfo pci_bus_info = {
 };
 
 static void pci_update_mappings(PCIDevice *d);
-static void pci_set_irq(void *opaque, int irq_num, int level);
+static void pci_set_irq(qemu_irq irq, void *opaque, int irq_num, int level);
 static int pci_add_option_rom(PCIDevice *pdev);
 
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
@@ -1037,7 +1037,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 /* generic PCI irq support */
 
 /* 0 <= irq_num <= 3. level must be 0 or 1 */
-static void pci_set_irq(void *opaque, int irq_num, int level)
+static void pci_set_irq(qemu_irq irq, void *opaque, int irq_num, int level)
 {
     PCIDevice *pci_dev = opaque;
     int change;
diff --git a/hw/pl061.c b/hw/pl061.c
index 7b1b636..e9490bb 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -209,12 +209,12 @@ static void pl061_reset(pl061_state *s)
   s->cr = 0xff;
 }
 
-static void pl061_set_irq(void * opaque, int irq, int level)
+static void pl061_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     pl061_state *s = (pl061_state *)opaque;
     uint8_t mask;
 
-    mask = 1 << irq;
+    mask = 1 << n;
     if ((s->dir & mask) == 0) {
         s->data &= ~mask;
         if (level)
diff --git a/hw/pl190.c b/hw/pl190.c
index a4bc9c1..a00d86b 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -54,14 +54,14 @@ static void pl190_update(pl190_state *s)
     qemu_set_irq(s->fiq, set);
 }
 
-static void pl190_set_irq(void *opaque, int irq, int level)
+static void pl190_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     pl190_state *s = (pl190_state *)opaque;
 
     if (level)
-        s->level |= 1u << irq;
+        s->level |= 1u << n;
     else
-        s->level &= ~(1u << irq);
+        s->level &= ~(1u << n);
     pl190_update(s);
 }
 
diff --git a/hw/ppc.c b/hw/ppc.c
index 2a77eb9..2aef868 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -64,7 +64,7 @@ static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
 }
 
 /* PowerPC 6xx / 7xx internal IRQ controller */
-static void ppc6xx_set_irq (void *opaque, int pin, int level)
+static void ppc6xx_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -154,7 +154,7 @@ void ppc6xx_irq_init (CPUState *env)
 
 #if defined(TARGET_PPC64)
 /* PowerPC 970 internal IRQ controller */
-static void ppc970_set_irq (void *opaque, int pin, int level)
+static void ppc970_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -238,7 +238,7 @@ void ppc970_irq_init (CPUState *env)
 #endif /* defined(TARGET_PPC64) */
 
 /* PowerPC 40x internal IRQ controller */
-static void ppc40x_set_irq (void *opaque, int pin, int level)
+static void ppc40x_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
@@ -316,7 +316,7 @@ void ppc40x_irq_init (CPUState *env)
 }
 
 /* PowerPC E500 internal IRQ controller */
-static void ppce500_set_irq (void *opaque, int pin, int level)
+static void ppce500_set_irq (qemu_irq irq, void *opaque, int pin, int level)
 {
     CPUState *env = opaque;
     int cur_level;
diff --git a/hw/ppc4xx_devs.c b/hw/ppc4xx_devs.c
index 37a3948..732b17d 100644
--- a/hw/ppc4xx_devs.c
+++ b/hw/ppc4xx_devs.c
@@ -147,7 +147,7 @@ static void ppcuic_trigger_irq (ppcuic_t *uic)
     }
 }
 
-static void ppcuic_set_irq (void *opaque, int irq_num, int level)
+static void ppcuic_set_irq (qemu_irq irq, void *opaque, int irq_num, int level)
 {
     ppcuic_t *uic;
     uint32_t mask, sr;
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 16c9950..fd1ca86 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -547,7 +547,7 @@ static CPUReadMemoryFunc * const PPC_prep_io_read[] = {
 
 #define NVRAM_SIZE        0x2000
 
-static void cpu_request_exit(void *opaque, int irq, int level)
+static void cpu_request_exit(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = cpu_single_env;
 
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9095386..aef4259 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2019,7 +2019,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(target_phys_addr_t base,
     return s;
 }
 
-static void pxa2xx_reset(void *opaque, int line, int level)
+static void pxa2xx_reset(qemu_irq irq, void *opaque, int line, int level)
 {
     PXA2xxState *s = (PXA2xxState *) opaque;
 
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index f354f4b..7a7e538 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -86,7 +86,7 @@ static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
     0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
 };
 
-static void pxa2xx_gpio_set(void *opaque, int line, int level)
+static void pxa2xx_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
     int bank;
diff --git a/hw/pxa2xx_pcmcia.c b/hw/pxa2xx_pcmcia.c
index be1309f..0e46d9e 100644
--- a/hw/pxa2xx_pcmcia.c
+++ b/hw/pxa2xx_pcmcia.c
@@ -121,7 +121,8 @@ static CPUWriteMemoryFunc * const pxa2xx_pcmcia_io_writefn[] = {
     pxa2xx_pcmcia_io_write,
 };
 
-static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
+static void pxa2xx_pcmcia_set_irq(qemu_irq irq, void *opaque, int line,
+                                  int level)
 {
     PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
     if (!s->irq)
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 0a98342..67163ce 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -67,16 +67,16 @@ static void pxa2xx_pic_update(void *opaque)
 
 /* Note: Here level means state of the signal on a pin, not
  * IRQ/FIQ distinction as in PXA Developer Manual.  */
-static void pxa2xx_pic_set_irq(void *opaque, int irq, int level)
+static void pxa2xx_pic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     PXA2xxPICState *s = (PXA2xxPICState *) opaque;
-    int int_set = (irq >= 32);
-    irq &= 31;
+    int int_set = (n >= 32);
+    n &= 31;
 
     if (level)
-        s->int_pending[int_set] |= 1 << irq;
+        s->int_pending[int_set] |= 1 << n;
     else
-        s->int_pending[int_set] &= ~(1 << irq);
+        s->int_pending[int_set] &= ~(1 << n);
 
     pxa2xx_pic_update(opaque);
 }
diff --git a/hw/r2d.c b/hw/r2d.c
index 38c4f6a..eb8e6e0 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -114,7 +114,7 @@ static void update_irl(r2d_fpga_t *fpga)
     qemu_set_irq(fpga->irl, irl ^ 15);
 }
 
-static void r2d_fpga_irq_set(void *opaque, int n, int level)
+static void r2d_fpga_irq_set(qemu_irq irq, void *opaque, int n, int level)
 {
     r2d_fpga_t *fpga = opaque;
     if (level)
diff --git a/hw/rc4030.c b/hw/rc4030.c
index 2a8233a..09260de 100644
--- a/hw/rc4030.c
+++ b/hw/rc4030.c
@@ -459,14 +459,15 @@ static void update_jazz_irq(rc4030State *s)
         qemu_irq_lower(s->jazz_bus_irq);
 }
 
-static void rc4030_irq_jazz_request(void *opaque, int irq, int level)
+static void rc4030_irq_jazz_request(qemu_irq irq, void *opaque, int n,
+                                    int level)
 {
     rc4030State *s = opaque;
 
     if (level) {
-        s->isr_jazz |= 1 << irq;
+        s->isr_jazz |= 1 << n;
     } else {
-        s->isr_jazz &= ~(1 << irq);
+        s->isr_jazz &= ~(1 << n);
     }
 
     update_jazz_irq(s);
diff --git a/hw/sbi.c b/hw/sbi.c
index c4adc09..0783efa 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -47,7 +47,7 @@ typedef struct SBIState {
 
 #define SBI_SIZE (SBI_NREGS * 4)
 
-static void sbi_set_irq(void *opaque, int irq, int level)
+static void sbi_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
 }
 
diff --git a/hw/sh_intc.c b/hw/sh_intc.c
index da36d32..8bb1b07 100644
--- a/hw/sh_intc.c
+++ b/hw/sh_intc.c
@@ -71,7 +71,7 @@ void sh_intc_toggle_source(struct intc_source *source,
   }
 }
 
-static void sh_intc_set_irq (void *opaque, int n, int level)
+static void sh_intc_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
   struct intc_desc *desc = opaque;
   struct intc_source *source = &(desc->sources[n]);
@@ -467,7 +467,7 @@ int sh_intc_init(struct intc_desc *desc,
 
 /* Assert level <n> IRL interrupt. 
    0:deassert. 1:lowest priority,... 15:highest priority. */
-void sh_intc_set_irl(void *opaque, int n, int level)
+void sh_intc_set_irl(qemu_irq irq, void *opaque, int n, int level)
 {
     struct intc_source *s = opaque;
     int i, irl = level ^ 15;
diff --git a/hw/sh_intc.h b/hw/sh_intc.h
index c117d6f..2dbe391 100644
--- a/hw/sh_intc.h
+++ b/hw/sh_intc.h
@@ -75,6 +75,6 @@ int sh_intc_init(struct intc_desc *desc,
 		 struct intc_prio_reg *prio_regs,
 		 int nr_prio_regs);
 
-void sh_intc_set_irl(void *opaque, int n, int level);
+void sh_intc_set_irl(qemu_irq irq, void *opaque, int n, int level);
 
 #endif /* __SH_INTC_H__ */
diff --git a/hw/sharpsl.h b/hw/sharpsl.h
index c5ccf79..ca7e001 100644
--- a/hw/sharpsl.h
+++ b/hw/sharpsl.h
@@ -13,7 +13,6 @@
 typedef struct ScoopInfo ScoopInfo;
 ScoopInfo *scoop_init(PXA2xxState *cpu,
                 int instance, target_phys_addr_t target_base);
-void scoop_gpio_set(void *opaque, int line, int level);
 qemu_irq *scoop_gpio_in_get(ScoopInfo *s);
 void scoop_gpio_out_set(ScoopInfo *s, int line,
                 qemu_irq handler);
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index b76d3ac..174ebca 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -317,14 +317,14 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
  * "irq" here is the bit number in the system interrupt register to
  * separate serial and keyboard interrupts sharing a level.
  */
-static void slavio_set_irq(void *opaque, int irq, int level)
+static void slavio_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     SLAVIO_INTCTLState *s = opaque;
-    uint32_t mask = 1 << irq;
-    uint32_t pil = intbit_to_level[irq];
+    uint32_t mask = 1 << n;
+    uint32_t pil = intbit_to_level[n];
     unsigned int i;
 
-    DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, irq, pil,
+    DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, n, pil,
             level);
     if (pil > 0) {
         if (level) {
@@ -364,12 +364,12 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
     slavio_check_interrupts(s, 1);
 }
 
-static void slavio_set_irq_all(void *opaque, int irq, int level)
+static void slavio_set_irq_all(qemu_irq irq, void *opaque, int n, int level)
 {
-    if (irq < 32) {
-        slavio_set_irq(opaque, irq, level);
+    if (n < 32) {
+        slavio_set_irq(irq, opaque, n, level);
     } else {
-        slavio_set_timer_irq_cpu(opaque, irq - 32, level);
+        slavio_set_timer_irq_cpu(opaque, n - 32, level);
     }
 }
 
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 5ae628d..337c2e1 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -95,7 +95,8 @@ static void slavio_misc_reset(DeviceState *d)
     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
 }
 
-static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
+static void slavio_set_power_fail(qemu_irq irq, void *opaque, int n,
+                                  int power_failing)
 {
     MiscState *s = opaque;
 
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index b521707..1e629da 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -127,7 +127,7 @@ void ledma_memory_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void dma_set_irq(void *opaque, int irq, int level)
+static void dma_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     DMAState *s = opaque;
     if (level) {
diff --git a/hw/spitz.c b/hw/spitz.c
index 4f82e24..010316c 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -253,7 +253,8 @@ static void spitz_keyboard_sense_update(SpitzKeyboardState *s)
     s->sense_state = sense;
 }
 
-static void spitz_keyboard_strobe(void *opaque, int line, int level)
+static void spitz_keyboard_strobe(qemu_irq irq, void *opaque, int line,
+                                  int level)
 {
     SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
 
@@ -649,7 +650,7 @@ static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
     return 0;
 }
 
-static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
+static void corgi_ssp_gpio_cs(qemu_irq irq, void *opaque, int line, int level)
 {
     CorgiSSPState *s = (CorgiSSPState *)opaque;
     assert(line >= 0 && line < 3);
@@ -769,7 +770,7 @@ static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
 #define SPITZ_GPIO_WM	5
 
 #ifdef HAS_AUDIO
-static void spitz_wm8750_addr(void *opaque, int line, int level)
+static void spitz_wm8750_addr(qemu_irq irq, void *opaque, int line, int level)
 {
     i2c_slave *wm = (i2c_slave *) opaque;
     if (level)
@@ -790,7 +791,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
     /* Attach a WM8750 to the bus */
     wm = i2c_create_slave(bus, "wm8750", 0);
 
-    spitz_wm8750_addr(wm, 0, 0);
+    spitz_wm8750_addr(NULL, wm, 0, 0);
     pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_WM,
                     qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
     /* .. and to the sound interface.  */
@@ -810,7 +811,7 @@ static void spitz_akita_i2c_setup(PXA2xxState *cpu)
 
 /* Other peripherals */
 
-static void spitz_out_switch(void *opaque, int line, int level)
+static void spitz_out_switch(qemu_irq irq, void *opaque, int line, int level)
 {
     switch (line) {
     case 0:
@@ -882,7 +883,8 @@ static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
 
 static int spitz_hsync;
 
-static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
+static void spitz_lcd_hsync_handler(qemu_irq irq, void *opaque, int line,
+                                    int level)
 {
     PXA2xxState *cpu = (PXA2xxState *) opaque;
     qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_HSYNC], spitz_hsync);
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index b632825..140f661 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -268,7 +268,7 @@ static void ssd0323_invalidate_display(void * opaque)
 }
 
 /* Command/data input.  */
-static void ssd0323_cd(void *opaque, int n, int level)
+static void ssd0323_cd(qemu_irq irq, void *opaque, int n, int level)
 {
     ssd0323_state *s = (ssd0323_state *)opaque;
     DPRINTF("%s mode\n", level ? "Data" : "Command");
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 5755f8a..45a11dd 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -974,7 +974,8 @@ static void stellaris_adc_update(stellaris_adc_state *s)
     }
 }
 
-static void stellaris_adc_trigger(void *opaque, int irq, int level)
+static void stellaris_adc_trigger(qemu_irq irq, void *opaque, int line,
+                                  int level)
 {
     stellaris_adc_state *s = (stellaris_adc_state *)opaque;
     int n;
@@ -1215,7 +1216,8 @@ typedef struct {
     SSIBus *bus[2];
 } stellaris_ssi_bus_state;
 
-static void stellaris_ssi_bus_select(void *opaque, int irq, int level)
+static void stellaris_ssi_bus_select(qemu_irq irq, void *opaque, int line,
+                                     int level)
 {
     stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
 
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 7d7542d..6c6f5bb 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -148,13 +148,13 @@ static void sun4c_check_interrupts(void *opaque)
 /*
  * "irq" here is the bit number in the system interrupt register
  */
-static void sun4c_set_irq(void *opaque, int irq, int level)
+static void sun4c_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     Sun4c_INTCTLState *s = opaque;
-    uint32_t mask = 1 << irq;
-    uint32_t pil = intbit_to_level[irq];
+    uint32_t mask = 1 << n;
+    uint32_t pil = intbit_to_level[n];
 
-    DPRINTF("Set irq %d -> pil %d level %d\n", irq, pil,
+    DPRINTF("Set irq %d -> pil %d level %d\n", n, pil,
             level);
     if (pil > 0) {
         if (level) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index e4ca8f3..bbfa4f4 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -255,23 +255,23 @@ void cpu_check_irqs(CPUState *env)
     }
 }
 
-static void cpu_set_irq(void *opaque, int irq, int level)
+static void cpu_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = opaque;
 
     if (level) {
-        DPRINTF("Raise CPU IRQ %d\n", irq);
+        DPRINTF("Raise CPU IRQ %d\n", n);
         env->halted = 0;
-        env->pil_in |= 1 << irq;
+        env->pil_in |= 1 << n;
         cpu_check_irqs(env);
     } else {
-        DPRINTF("Lower CPU IRQ %d\n", irq);
-        env->pil_in &= ~(1 << irq);
+        DPRINTF("Lower CPU IRQ %d\n", n);
+        env->pil_in &= ~(1 << n);
         cpu_check_irqs(env);
     }
 }
 
-static void dummy_cpu_set_irq(void *opaque, int irq, int level)
+static void dummy_cpu_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
 }
 
@@ -291,7 +291,7 @@ static void secondary_cpu_reset(void *opaque)
     env->halted = 1;
 }
 
-static void cpu_halt_signal(void *opaque, int irq, int level)
+static void cpu_halt_signal(qemu_irq irq, void *opaque, int n, int level)
 {
     if (level && cpu_single_env)
         cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 40b5f1f..0df1051 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -299,18 +299,18 @@ static void cpu_kick_irq(CPUState *env)
     cpu_check_irqs(env);
 }
 
-static void cpu_set_irq(void *opaque, int irq, int level)
+static void cpu_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     CPUState *env = opaque;
 
     if (level) {
-        CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq);
+        CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", n);
         env->halted = 0;
-        env->pil_in |= 1 << irq;
+        env->pil_in |= 1 << n;
         cpu_check_irqs(env);
     } else {
-        CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq);
-        env->pil_in &= ~(1 << irq);
+        CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", n);
+        env->pil_in &= ~(1 << n);
         cpu_check_irqs(env);
     }
 }
@@ -532,7 +532,7 @@ static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
     }
 }
 
-static void dummy_isa_irq_handler(void *opaque, int n, int level)
+static void dummy_isa_irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
 }
 
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index f3a1767..d108712 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -67,15 +67,15 @@ static void syborg_int_update(SyborgIntState *s)
     qemu_set_irq(s->parent_irq, s->pending_count > 0);
 }
 
-static void syborg_int_set_irq(void *opaque, int irq, int level)
+static void syborg_int_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     SyborgIntState *s = (SyborgIntState *)opaque;
 
-    if (s->flags[irq].level == level)
+    if (s->flags[n].level == level)
         return;
 
-    s->flags[irq].level = level;
-    if (s->flags[irq].enabled) {
+    s->flags[n].level = level;
+    if (s->flags[n].enabled) {
         if (level)
             s->pending_count++;
         else
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index e0c5e5f..ff8165a 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -135,7 +135,7 @@ qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s)
     return s->gpio_in;
 }
 
-static void tc6393xb_gpio_set(void *opaque, int line, int level)
+static void tc6393xb_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
 //    TC6393xbState *s = opaque;
 
@@ -178,14 +178,15 @@ qemu_irq tc6393xb_l3v_get(TC6393xbState *s)
     return s->l3v;
 }
 
-static void tc6393xb_l3v(void *opaque, int line, int level)
+static void tc6393xb_l3v(qemu_irq irq, void *opaque, int line, int level)
 {
     TC6393xbState *s = opaque;
     s->blank = !level;
     fprintf(stderr, "L3V: %d\n", level);
 }
 
-static void tc6393xb_sub_irq(void *opaque, int line, int level) {
+static void tc6393xb_sub_irq(qemu_irq irq, void *opaque, int line, int level)
+{
     TC6393xbState *s = opaque;
     uint8_t isr = s->scr.ISR;
     if (level)
diff --git a/hw/tosa.c b/hw/tosa.c
index fbe8d8c..2a1954b 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -62,7 +62,7 @@ static void tosa_microdrive_attach(PXA2xxState *cpu)
     }
 }
 
-static void tosa_out_switch(void *opaque, int line, int level)
+static void tosa_out_switch(qemu_irq irq, void *opaque, int line, int level)
 {
     switch (line) {
         case 0:
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 4864be5..ab28667 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -678,7 +678,8 @@ static void tusb_power_tick(void *opaque)
     }
 }
 
-static void tusb_musb_core_intr(void *opaque, int source, int level)
+static void tusb_musb_core_intr(qemu_irq irq, void *opaque, int source,
+                                int level)
 {
     TUSBState *s = (TUSBState *) opaque;
     uint16_t otg_status = s->otg_status;
diff --git a/hw/twl92230.c b/hw/twl92230.c
index e61f17f..3ab8dfd 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -183,7 +183,7 @@ static void menelaus_reset(i2c_slave *i2c)
     menelaus_update(s);
 }
 
-static void menelaus_gpio_set(void *opaque, int line, int level)
+static void menelaus_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     MenelausState *s = (MenelausState *) opaque;
 
@@ -192,7 +192,8 @@ static void menelaus_gpio_set(void *opaque, int line, int level)
     s->inputs |= level << line;
 }
 
-static void menelaus_pwrbtn_set(void *opaque, int line, int level)
+static void menelaus_pwrbtn_set(qemu_irq irq, void *opaque, int line,
+                                int level)
 {
     MenelausState *s = (MenelausState *) opaque;
 
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 391f5b8..49a780a 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -50,15 +50,15 @@ static void vpb_sic_update_pic(vpb_sic_state *s)
     }
 }
 
-static void vpb_sic_set_irq(void *opaque, int irq, int level)
+static void vpb_sic_set_irq(qemu_irq irq, void *opaque, int n, int level)
 {
     vpb_sic_state *s = (vpb_sic_state *)opaque;
     if (level)
-        s->level |= 1u << irq;
+        s->level |= 1u << n;
     else
-        s->level &= ~(1u << irq);
-    if (s->pic_enable & (1u << irq))
-        qemu_set_irq(s->parent[irq], level);
+        s->level &= ~(1u << n);
+    if (s->pic_enable & (1u << n))
+        qemu_set_irq(s->parent[n], level);
     vpb_sic_update(s);
 }
 
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 8ef6474..20b0267 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -126,7 +126,7 @@ static CPUWriteMemoryFunc * const pic_write[] = {
     &pic_writel,
 };
 
-static void irq_handler(void *opaque, int irq, int level)
+static void irq_handler(qemu_irq irq, void *opaque, int n, int level)
 {
     struct xlx_pic *p = opaque;
 
@@ -138,9 +138,9 @@ static void irq_handler(void *opaque, int irq, int level)
     /* Update source flops. Don't clear unless level triggered.
        Edge triggered interrupts only go away when explicitely acked to
        the interrupt controller.  */
-    if (!(p->c_kind_of_intr & (1 << irq)) || level) {
-        p->regs[R_ISR] &= ~(1 << irq);
-        p->regs[R_ISR] |= (level << irq);
+    if (!(p->c_kind_of_intr & (1 << n)) || level) {
+        p->regs[R_ISR] &= ~(1 << n);
+        p->regs[R_ISR] |= (level << n);
     }
     update_irq(p);
 }
diff --git a/hw/zaurus.c b/hw/zaurus.c
index db6ba75..94c4ad7 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -153,7 +153,7 @@ static CPUWriteMemoryFunc * const scoop_writefn[] = {
     scoop_writeb,
 };
 
-void scoop_gpio_set(void *opaque, int line, int level)
+static void scoop_gpio_set(qemu_irq irq, void *opaque, int line, int level)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
 

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-06  8:10 ` [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs Jan Kiszka
@ 2010-06-12 12:21   ` Paul Brook
  2010-06-12 12:32     ` Jan Kiszka
  2010-06-12 13:44     ` Blue Swirl
  0 siblings, 2 replies; 44+ messages in thread
From: Paul Brook @ 2010-06-12 12:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: blue Swirl, Jan Kiszka, Jan Kiszka, Gleb Natapov, Juan Quintela

> This patch allows to optionally attach a message to an IRQ event. The
> message can contain a payload reference and a callback that the IRQ
> handler may invoke to report the delivery result. The former can be used
> to model message signaling interrupts, the latter to cleanly implement
> IRQ de-coalescing logics.

I don't like this. qemu_irq is a level triggered interface. Redundant calls to 
qemu_set_irq should (in principle) be a no-op.  If you want message passing 
then IMO you should be using something else.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 12:21   ` Paul Brook
@ 2010-06-12 12:32     ` Jan Kiszka
  2010-06-12 13:44     ` Blue Swirl
  1 sibling, 0 replies; 44+ messages in thread
From: Jan Kiszka @ 2010-06-12 12:32 UTC (permalink / raw)
  To: Paul Brook
  Cc: blue Swirl, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

[-- Attachment #1: Type: text/plain, Size: 1212 bytes --]

Paul Brook wrote:
>> This patch allows to optionally attach a message to an IRQ event. The
>> message can contain a payload reference and a callback that the IRQ
>> handler may invoke to report the delivery result. The former can be used
>> to model message signaling interrupts, the latter to cleanly implement
>> IRQ de-coalescing logics.
> 
> I don't like this. qemu_irq is a level triggered interface. Redundant calls to 
> qemu_set_irq should (in principle) be a no-op.  If you want message passing 
> then IMO you should be using something else.

I think we all now agree that we need some extension to the qemu_irq
interface to realize clean irq de-coalescing.

Returning a delivery code was proposed several times but always
rejected. Blueswirl brought up that message passing can model this as
well and that it has additional use for sparc. So I followed this
suggestion, specifically due to the added value and the absence of
concerns by other parties. Now, after spending yet another "few" hours
on this series, you raise a new concern. Wouldn't it be possible to do
this during the design discussion?

OK, what is your proposal now for an IRQ de-coalescing framework?

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 12:21   ` Paul Brook
  2010-06-12 12:32     ` Jan Kiszka
@ 2010-06-12 13:44     ` Blue Swirl
  2010-06-12 14:15       ` Paul Brook
  1 sibling, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-12 13:44 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sat, Jun 12, 2010 at 12:21 PM, Paul Brook <paul@codesourcery.com> wrote:
>> This patch allows to optionally attach a message to an IRQ event. The
>> message can contain a payload reference and a callback that the IRQ
>> handler may invoke to report the delivery result. The former can be used
>> to model message signaling interrupts, the latter to cleanly implement
>> IRQ de-coalescing logics.
>
> I don't like this. qemu_irq is a level triggered interface. Redundant calls to
> qemu_set_irq should (in principle) be a no-op.  If you want message passing
> then IMO you should be using something else.

Keeping the optional message and qemu_irq together means that we can
reuse the existing IRQ subsystem. I'd guess something more separated
would need duplicate allocation and delivery support and maybe even
SysBus etc. would need lots of work to support a new class of IRQs.

Also detection of coalesced interrupts depends on reliably detecting
sort of redundant calls to qemu_set_irq. There we don't model real
level triggered hardware exactly but add some extra magic.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 13:44     ` Blue Swirl
@ 2010-06-12 14:15       ` Paul Brook
  2010-06-12 14:35         ` Blue Swirl
  2010-06-13 16:34         ` Paul Brook
  0 siblings, 2 replies; 44+ messages in thread
From: Paul Brook @ 2010-06-12 14:15 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> On Sat, Jun 12, 2010 at 12:21 PM, Paul Brook <paul@codesourcery.com> wrote:
> >> This patch allows to optionally attach a message to an IRQ event. The
> >> message can contain a payload reference and a callback that the IRQ
> >> handler may invoke to report the delivery result. The former can be used
> >> to model message signaling interrupts, the latter to cleanly implement
> >> IRQ de-coalescing logics.
> > 
> > I don't like this. qemu_irq is a level triggered interface. Redundant
> > calls to qemu_set_irq should (in principle) be a no-op.  If you want
> > message passing then IMO you should be using something else.
> 
> Keeping the optional message and qemu_irq together means that we can
> reuse the existing IRQ subsystem. I'd guess something more separated
> would need duplicate allocation and delivery support and maybe even
> SysBus etc. would need lots of work to support a new class of IRQs.

How do you propose message passing is handled when you have nested multi-layer 
interrupt trees? How long is the message data valid for? Who owns it? How is a 
receiver meant to know for format of the message being delivered, and who it's 
intended for?

IMO message triggered systems are fundamentally different to level states. 
qemu_irq represents a level state, and I'd really like for it to stay that 
way.  

If we need/want a generic message passing interface, then that's a different 
problem, and needs to be done in such a way that the devices always agree on 
the type of message being passed.

TBH I preferred the original system whereby the source can query the state of 
the sink (i.e "are you ignoring this line?").  Note that conceptually this 
should be *querying* state, not responding to an event.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 14:15       ` Paul Brook
@ 2010-06-12 14:35         ` Blue Swirl
  2010-06-12 15:58           ` Paul Brook
  2010-06-13 16:34         ` Paul Brook
  1 sibling, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-12 14:35 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sat, Jun 12, 2010 at 2:15 PM, Paul Brook <paul@codesourcery.com> wrote:
>> On Sat, Jun 12, 2010 at 12:21 PM, Paul Brook <paul@codesourcery.com> wrote:
>> >> This patch allows to optionally attach a message to an IRQ event. The
>> >> message can contain a payload reference and a callback that the IRQ
>> >> handler may invoke to report the delivery result. The former can be used
>> >> to model message signaling interrupts, the latter to cleanly implement
>> >> IRQ de-coalescing logics.
>> >
>> > I don't like this. qemu_irq is a level triggered interface. Redundant
>> > calls to qemu_set_irq should (in principle) be a no-op.  If you want
>> > message passing then IMO you should be using something else.
>>
>> Keeping the optional message and qemu_irq together means that we can
>> reuse the existing IRQ subsystem. I'd guess something more separated
>> would need duplicate allocation and delivery support and maybe even
>> SysBus etc. would need lots of work to support a new class of IRQs.
>
> How do you propose message passing is handled when you have nested multi-layer
> interrupt trees?

Do we have such trees somewhere? I think message passing interrupts
are only used in bus based systems, like PCI or UPA/JBUS etc. I don't
know how LAPIC/IOAPIC bus works, it could be similar.

> How long is the message data valid for?

Currently it's valid for the duration of the call. It may make sense
to extend that later in order to handle EOIs.

> Who owns it?

The source.

> How is a
> receiver meant to know for format of the message being delivered, and who it's
> intended for?

This depends on the architecture. On Sparc64 the message is specified
by the guest or OF.

> IMO message triggered systems are fundamentally different to level states.
> qemu_irq represents a level state, and I'd really like for it to stay that
> way.

In real HW (MSI or Sparc64 mondo interrupts) a bus delivers the
message. But our buses only handle address and data lines.

> If we need/want a generic message passing interface, then that's a different
> problem, and needs to be done in such a way that the devices always agree on
> the type of message being passed.
>
> TBH I preferred the original system whereby the source can query the state of
> the sink (i.e "are you ignoring this line?").  Note that conceptually this
> should be *querying* state, not responding to an event.

It's simple, but I think too simple. It would work for the coalescing
interrupt hack but useless for other things.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 14:35         ` Blue Swirl
@ 2010-06-12 15:58           ` Paul Brook
  2010-06-12 19:33             ` Blue Swirl
  0 siblings, 1 reply; 44+ messages in thread
From: Paul Brook @ 2010-06-12 15:58 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> I think message passing interrupts
> are only used in bus based systems, like PCI or UPA/JBUS etc. I don't
> know how LAPIC/IOAPIC bus works, it could be similar.

PCI Message Signalled Interrupts use a regular data write, and we model it 
exactly that way. Under normal circumstances you program the device to write 
to memory mapped APIC control registers, but there's no real reason why you 
couldn't write to RAM.

LAPIC/IOAPIC have their own bus. On some hardware this is multiplexed over the 
main system bus, but logically it is a separate interconnect.

The fact that these a bus based systems suggests against using qemu_irq, which 
is an inherently point-point system.

> > How is a
> > receiver meant to know for format of the message being delivered, and who
> > it's intended for?
> 
> This depends on the architecture. On Sparc64 the message is specified
> by the guest or OF.
>...
> In real HW (MSI or Sparc64 mondo interrupts) a bus delivers the
> message. But our buses only handle address and data lines.

IIUC you're trying to use qemu_irq as a generic interconnect between devices. 
I think that's going to cause more problems than it solves.  If a bus has 
additional message passing capabilities then this can be part of the bus 
interface.

If two devices need a private communication channel then we probably want some 
implementation agnostic way of defining this link.  Connecting LAPIC to IOAPIC 
is a potential example of this. However this needs to be done in a type-safe 
manner.  DMA channels may be another potential use of this linking. We'd want 
to avoid connecting a DMA channel to an APIC.

[*] A simple unidirectional dma request line is suitable for qmu_irq. A DMA 
system that transfers data outside of memory read/write transactions is not. 
e.g. ISA effectively defines a regular memory bus plus 8 bidirectional data 
streams (aka DMA channels). These are multiplexed over the same physical pins, 
but logically distinct. The DMA channels could either be bundled up into the 
ISA bus interface, or modelled as links between devices and the DMA 
controller.

> > TBH I preferred the original system whereby the source can query the
> > state of the sink (i.e "are you ignoring this line?").  Note that
> > conceptually this should be querying state, not responding to an event.
> 
> It's simple, but I think too simple. It would work for the coalescing
> interrupt hack but useless for other things.

I'm not convinced making qemu_irq do "other things" is a good idea.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 15:58           ` Paul Brook
@ 2010-06-12 19:33             ` Blue Swirl
  2010-06-12 20:15               ` Paul Brook
  2010-06-12 20:32               ` Blue Swirl
  0 siblings, 2 replies; 44+ messages in thread
From: Blue Swirl @ 2010-06-12 19:33 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sat, Jun 12, 2010 at 3:58 PM, Paul Brook <paul@codesourcery.com> wrote:
>> I think message passing interrupts
>> are only used in bus based systems, like PCI or UPA/JBUS etc. I don't
>> know how LAPIC/IOAPIC bus works, it could be similar.
>
> PCI Message Signalled Interrupts use a regular data write, and we model it
> exactly that way. Under normal circumstances you program the device to write
> to memory mapped APIC control registers, but there's no real reason why you
> couldn't write to RAM.
>
> LAPIC/IOAPIC have their own bus. On some hardware this is multiplexed over the
> main system bus, but logically it is a separate interconnect.
>
> The fact that these a bus based systems suggests against using qemu_irq, which
> is an inherently point-point system.
>
>> > How is a
>> > receiver meant to know for format of the message being delivered, and who
>> > it's intended for?
>>
>> This depends on the architecture. On Sparc64 the message is specified
>> by the guest or OF.
>>...
>> In real HW (MSI or Sparc64 mondo interrupts) a bus delivers the
>> message. But our buses only handle address and data lines.
>
> IIUC you're trying to use qemu_irq as a generic interconnect between devices.
> I think that's going to cause more problems than it solves.  If a bus has
> additional message passing capabilities then this can be part of the bus
> interface.
>
> If two devices need a private communication channel then we probably want some
> implementation agnostic way of defining this link.  Connecting LAPIC to IOAPIC
> is a potential example of this. However this needs to be done in a type-safe
> manner.  DMA channels may be another potential use of this linking. We'd want
> to avoid connecting a DMA channel to an APIC.
>
> [*] A simple unidirectional dma request line is suitable for qmu_irq. A DMA
> system that transfers data outside of memory read/write transactions is not.
> e.g. ISA effectively defines a regular memory bus plus 8 bidirectional data
> streams (aka DMA channels). These are multiplexed over the same physical pins,
> but logically distinct. The DMA channels could either be bundled up into the
> ISA bus interface, or modelled as links between devices and the DMA
> controller.

Very very interesting. There's some out of band data related to DMA
(bus errors, IOMMU faults, ISA DREQ) which hasn't been covered in
previous Generic DMA proposals. Maybe all we need is a generic side
band link, which would be usable for point to point (qemu_irq,
coalescing, messages) and bus channels?

>> > TBH I preferred the original system whereby the source can query the
>> > state of the sink (i.e "are you ignoring this line?").  Note that
>> > conceptually this should be querying state, not responding to an event.
>>
>> It's simple, but I think too simple. It would work for the coalescing
>> interrupt hack but useless for other things.
>
> I'm not convinced making qemu_irq do "other things" is a good idea.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 19:33             ` Blue Swirl
@ 2010-06-12 20:15               ` Paul Brook
  2010-06-12 20:32               ` Blue Swirl
  1 sibling, 0 replies; 44+ messages in thread
From: Paul Brook @ 2010-06-12 20:15 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> > [*] A simple unidirectional dma request line is suitable for qmu_irq. A
> > DMA system that transfers data outside of memory read/write transactions
> > is not. e.g. ISA effectively defines a regular memory bus plus 8
> > bidirectional data streams (aka DMA channels). These are multiplexed
> > over the same physical pins, but logically distinct. The DMA channels
> > could either be bundled up into the ISA bus interface, or modelled as
> > links between devices and the DMA controller.
> 
> Very very interesting. There's some out of band data related to DMA
> (bus errors, IOMMU faults, ISA DREQ) which hasn't been covered in
> previous Generic DMA proposals.

I suspect you're confusing two different concepts - bus-master DMA (memory 
accesses generated by devices) v.s. IO channel DMA (out of band data stream 
between a device and a third party DMA engine). Despite both being called 
"DMA", they significantly different beasts. The IO channel DMA master is 
effectively a bridge between the memory bus (accessed via bus-master DMA) and 
the device IO channel.

Note that actual IO channel DMA is relatively rare. While many embedded 
devices still have a DMA engine this tends to generate regular memory 
accesses, which are then programmed to access a memory mapped FIFO. This 
shouldn't need any special magic to implement, typically just a simple 
qemu_irq control line.

> Maybe all we need is a generic side
> band link, which would be usable for point to point (qemu_irq,
> coalescing, messages) and bus channels?

We may want to consider a common mechanism for mapping links between devices. 
i.e some way of saying "Connect device X port N to device Y port M". In the 
case of traditional interrupts each IRQ source or sink would be a "port". For 
a bus system you'd probably want to connect them all to a [virtual] bus 
arbiter object.

This should allow the mapping core to verify that e.g. you're not connecting a 
qemu_irq to something expecting an apic_message, preferably without knowing or 
caring how either of those work.

In theory I guess you could also use the same mechanism to connect network 
devices to their host interface, etc.  I haven't thought this bit through 
fully, so this may be excessively clever.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 19:33             ` Blue Swirl
  2010-06-12 20:15               ` Paul Brook
@ 2010-06-12 20:32               ` Blue Swirl
  2010-06-13  6:47                 ` Blue Swirl
  2010-06-13 15:49                 ` Paul Brook
  1 sibling, 2 replies; 44+ messages in thread
From: Blue Swirl @ 2010-06-12 20:32 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sat, Jun 12, 2010 at 7:33 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Sat, Jun 12, 2010 at 3:58 PM, Paul Brook <paul@codesourcery.com> wrote:
>>> I think message passing interrupts
>>> are only used in bus based systems, like PCI or UPA/JBUS etc. I don't
>>> know how LAPIC/IOAPIC bus works, it could be similar.
>>
>> PCI Message Signalled Interrupts use a regular data write, and we model it
>> exactly that way. Under normal circumstances you program the device to write
>> to memory mapped APIC control registers, but there's no real reason why you
>> couldn't write to RAM.
>>
>> LAPIC/IOAPIC have their own bus. On some hardware this is multiplexed over the
>> main system bus, but logically it is a separate interconnect.
>>
>> The fact that these a bus based systems suggests against using qemu_irq, which
>> is an inherently point-point system.
>>
>>> > How is a
>>> > receiver meant to know for format of the message being delivered, and who
>>> > it's intended for?
>>>
>>> This depends on the architecture. On Sparc64 the message is specified
>>> by the guest or OF.
>>>...
>>> In real HW (MSI or Sparc64 mondo interrupts) a bus delivers the
>>> message. But our buses only handle address and data lines.
>>
>> IIUC you're trying to use qemu_irq as a generic interconnect between devices.
>> I think that's going to cause more problems than it solves.  If a bus has
>> additional message passing capabilities then this can be part of the bus
>> interface.
>>
>> If two devices need a private communication channel then we probably want some
>> implementation agnostic way of defining this link.  Connecting LAPIC to IOAPIC
>> is a potential example of this. However this needs to be done in a type-safe
>> manner.  DMA channels may be another potential use of this linking. We'd want
>> to avoid connecting a DMA channel to an APIC.
>>
>> [*] A simple unidirectional dma request line is suitable for qmu_irq. A DMA
>> system that transfers data outside of memory read/write transactions is not.
>> e.g. ISA effectively defines a regular memory bus plus 8 bidirectional data
>> streams (aka DMA channels). These are multiplexed over the same physical pins,
>> but logically distinct. The DMA channels could either be bundled up into the
>> ISA bus interface, or modelled as links between devices and the DMA
>> controller.
>
> Very very interesting. There's some out of band data related to DMA
> (bus errors, IOMMU faults, ISA DREQ) which hasn't been covered in
> previous Generic DMA proposals. Maybe all we need is a generic side
> band link, which would be usable for point to point (qemu_irq,
> coalescing, messages) and bus channels?

I think we could solve all problems (well, maybe not world peace, yet)
by switching to message based system for all of DMA and IRQs.

Each device would have a message input port and way to output messages.

Examples:

Zero copy memory access from device D1 to D2 to host memory (D3) with
access broken to page length units and errors occurring on the last
byte:
D1 send_msg(ID, MSG_MEM_WRITE, DMA address, length) -> D2
D2 send_msg(ID, MSG_MEM_WRITE, DMA address2, length) -> D3
D3 send_replymsg(ID, MSG_MEM_PTR, host address, 4096) -> D2
D2 send_replymsg(ID, MSG_MEM_PTR, host address, 4096) -> D1
D3 send_replymsg(ID, MSG_MEM_PTR, host address, length - 4096 - 1) -> D2
D2 send_replymsg(ID, MSG_MEM_PTR, host address, length - 4096 - 1) -> D1
D3 send_replymsg(ID, MSG_MEM_ERROR, DMA address2 + length - 1, 1, status) -> D2
D2 send_replymsg(ID, MSG_MEM_ERROR, DMA address + length - 1, 1, status) -> D1

IRQ delivery chain D1->D2->D3 with coalescing, messages, delivery
reporting and EOI:
D1 send_msg(ID, MSG_IRQ_RAISE, payload) -> D2
D2 send_msg(ID, MSG_IRQ_RAISE, payload) -> D3
D3 send_replymsg(ID, MSG_IRQ_STATUS, MI_COALESCED) -> D2
D2 send_replymsg(ID, MSG_IRQ_STATUS, MI_COALESCED) -> D1
D3 send_replymsg(ID, MSG_IRQ_STATUS, MI_DELIVERED) -> D2
D2 send_replymsg(ID, MSG_IRQ_STATUS, MI_DELIVERED) -> D1
D3 send_replymsg(ID, MSG_IRQ_STATUS, MI_EOI) -> D2
D2 send_replymsg(ID, MSG_IRQ_STATUS, MI_EOI) -> D1

What else do we want? :-)

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 20:32               ` Blue Swirl
@ 2010-06-13  6:47                 ` Blue Swirl
  2010-06-13 15:49                 ` Paul Brook
  1 sibling, 0 replies; 44+ messages in thread
From: Blue Swirl @ 2010-06-13  6:47 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sat, Jun 12, 2010 at 8:32 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
> On Sat, Jun 12, 2010 at 7:33 PM, Blue Swirl <blauwirbel@gmail.com> wrote:
>> On Sat, Jun 12, 2010 at 3:58 PM, Paul Brook <paul@codesourcery.com> wrote:
>>>> I think message passing interrupts
>>>> are only used in bus based systems, like PCI or UPA/JBUS etc. I don't
>>>> know how LAPIC/IOAPIC bus works, it could be similar.
>>>
>>> PCI Message Signalled Interrupts use a regular data write, and we model it
>>> exactly that way. Under normal circumstances you program the device to write
>>> to memory mapped APIC control registers, but there's no real reason why you
>>> couldn't write to RAM.
>>>
>>> LAPIC/IOAPIC have their own bus. On some hardware this is multiplexed over the
>>> main system bus, but logically it is a separate interconnect.
>>>
>>> The fact that these a bus based systems suggests against using qemu_irq, which
>>> is an inherently point-point system.
>>>
>>>> > How is a
>>>> > receiver meant to know for format of the message being delivered, and who
>>>> > it's intended for?
>>>>
>>>> This depends on the architecture. On Sparc64 the message is specified
>>>> by the guest or OF.
>>>>...
>>>> In real HW (MSI or Sparc64 mondo interrupts) a bus delivers the
>>>> message. But our buses only handle address and data lines.
>>>
>>> IIUC you're trying to use qemu_irq as a generic interconnect between devices.
>>> I think that's going to cause more problems than it solves.  If a bus has
>>> additional message passing capabilities then this can be part of the bus
>>> interface.
>>>
>>> If two devices need a private communication channel then we probably want some
>>> implementation agnostic way of defining this link.  Connecting LAPIC to IOAPIC
>>> is a potential example of this. However this needs to be done in a type-safe
>>> manner.  DMA channels may be another potential use of this linking. We'd want
>>> to avoid connecting a DMA channel to an APIC.
>>>
>>> [*] A simple unidirectional dma request line is suitable for qmu_irq. A DMA
>>> system that transfers data outside of memory read/write transactions is not.
>>> e.g. ISA effectively defines a regular memory bus plus 8 bidirectional data
>>> streams (aka DMA channels). These are multiplexed over the same physical pins,
>>> but logically distinct. The DMA channels could either be bundled up into the
>>> ISA bus interface, or modelled as links between devices and the DMA
>>> controller.
>>
>> Very very interesting. There's some out of band data related to DMA
>> (bus errors, IOMMU faults, ISA DREQ) which hasn't been covered in
>> previous Generic DMA proposals. Maybe all we need is a generic side
>> band link, which would be usable for point to point (qemu_irq,
>> coalescing, messages) and bus channels?
>
> I think we could solve all problems (well, maybe not world peace, yet)
> by switching to message based system for all of DMA and IRQs.
>
> Each device would have a message input port and way to output messages.
>
> Examples:
>
> Zero copy memory access from device D1 to D2 to host memory (D3) with
> access broken to page length units and errors occurring on the last
> byte:
> D1 send_msg(ID, MSG_MEM_WRITE, DMA address, length) -> D2
> D2 send_msg(ID, MSG_MEM_WRITE, DMA address2, length) -> D3
> D3 send_replymsg(ID, MSG_MEM_PTR, host address, 4096) -> D2
> D2 send_replymsg(ID, MSG_MEM_PTR, host address, 4096) -> D1
> D3 send_replymsg(ID, MSG_MEM_PTR, host address, length - 4096 - 1) -> D2
> D2 send_replymsg(ID, MSG_MEM_PTR, host address, length - 4096 - 1) -> D1
> D3 send_replymsg(ID, MSG_MEM_ERROR, DMA address2 + length - 1, 1, status) -> D2
> D2 send_replymsg(ID, MSG_MEM_ERROR, DMA address + length - 1, 1, status) -> D1

This could be implemented with small modifications to existing
cpu_physical_memory_rw() interface. Improved devices would check if a
channel back has been registered. If not, current methods are used,
same with unimproved devices. If yes, translated pointers will flow
back for zero copy DMA.

> IRQ delivery chain D1->D2->D3 with coalescing, messages, delivery
> reporting and EOI:
> D1 send_msg(ID, MSG_IRQ_RAISE, payload) -> D2
> D2 send_msg(ID, MSG_IRQ_RAISE, payload) -> D3
> D3 send_replymsg(ID, MSG_IRQ_STATUS, MI_COALESCED) -> D2
> D2 send_replymsg(ID, MSG_IRQ_STATUS, MI_COALESCED) -> D1
> D3 send_replymsg(ID, MSG_IRQ_STATUS, MI_DELIVERED) -> D2
> D2 send_replymsg(ID, MSG_IRQ_STATUS, MI_DELIVERED) -> D1
> D3 send_replymsg(ID, MSG_IRQ_STATUS, MI_EOI) -> D2
> D2 send_replymsg(ID, MSG_IRQ_STATUS, MI_EOI) -> D1

Same here: send_msg could be in fact be qemu_irq_raise(). Without a
return chain, no replies will be sent. For messages, an augmented
forward chain must exist, otherwise the messages will be ignored.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 20:32               ` Blue Swirl
  2010-06-13  6:47                 ` Blue Swirl
@ 2010-06-13 15:49                 ` Paul Brook
  2010-06-13 18:17                   ` Blue Swirl
  1 sibling, 1 reply; 44+ messages in thread
From: Paul Brook @ 2010-06-13 15:49 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> I think we could solve all problems (well, maybe not world peace, yet)
> by switching to message based system for all of DMA and IRQs.
> 
> Each device would have a message input port and way to output messages.
> 
> Examples:
> 
> Zero copy memory access from device D1 to D2 to host memory (D3) with
> access broken to page length units and errors occurring on the last
> byte:
> D1 send_msg(ID, MSG_MEM_WRITE, DMA address, length) -> D2
>...
> IRQ delivery chain D1->D2->D3 with coalescing, messages, delivery
> reporting and EOI:
> D1 send_msg(ID, MSG_IRQ_RAISE, payload) -> D2

This feels like a terrible idea to me. It introduces an unnecessary RPC 
indirection layer without actually solving any of the problems. It just makes 
it harder (if not impossible) for the compiler to verify any of the interfaces 
between objects.

If we need a mechanism for a device to query the state of its outgoing IRQ 
lines (which is what I mentioned previously), then we can just add that. I 
still maintain that qemu_irq is *not* a message passing interface, and that 
this absence is a good thing. Maybe if I make the qemu_irq code actively 
suppress redundant level change notices that would make things clearer.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-12 14:15       ` Paul Brook
  2010-06-12 14:35         ` Blue Swirl
@ 2010-06-13 16:34         ` Paul Brook
  2010-06-13 18:04           ` Blue Swirl
  2010-06-14  5:40           ` Gleb Natapov
  1 sibling, 2 replies; 44+ messages in thread
From: Paul Brook @ 2010-06-13 16:34 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> TBH I preferred the original system whereby the source can query the state
> of the sink (i.e "are you ignoring this line?").  Note that conceptually
> this should be *querying* state, not responding to an event.

People are still pushing qemu_irq as an message passing interface, so I'm 
going to expand a bit more on how I think this could be avoided.

Start with the assumption that qemu irq represents a single bit of 
information. The current implementation is stateless, but in principle it 
could remember its state and ignore redundant calls to qemu_set_irq.

In order to workaround the periodic timer issue, we need some way of for the 
source device to interrogate the target device state relating to this link. 
The suggestions so far are along the lines of "what happened when I made this 
change". This makes me unhappy, because it's overlaying event semantics on top 
of a state based system.

Instead I suggest that we should be describing what the target state 
associated with this input is.  Suitable return values could be:
 * normal: This input effects the state of the target device. Note that this 
need not imply that changing the input actually effects the output at this 
time. e.g. if an interrupt controller is already processing a higher priority 
input, the low priority inputs should still return "normal" - the input will 
be processed once the unrelated high priority input is finished.
 * latched: This input has already effected target device state, and will be 
ignored until reset by some external event. Typically means an interrupt 
controller latches its inputs, and this input has already been latched.
 * masked: This input is ignored.

In practice these should give approximately the same information as event 
based delivered/coalesced/dropped responses.  The difference is that they are 
consistent with the state based nature of qemu_irq.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-13 16:34         ` Paul Brook
@ 2010-06-13 18:04           ` Blue Swirl
  2010-06-14  5:40           ` Gleb Natapov
  1 sibling, 0 replies; 44+ messages in thread
From: Blue Swirl @ 2010-06-13 18:04 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sun, Jun 13, 2010 at 4:34 PM, Paul Brook <paul@codesourcery.com> wrote:
>> TBH I preferred the original system whereby the source can query the state
>> of the sink (i.e "are you ignoring this line?").  Note that conceptually
>> this should be *querying* state, not responding to an event.
>
> People are still pushing qemu_irq as an message passing interface, so I'm
> going to expand a bit more on how I think this could be avoided.
>
> Start with the assumption that qemu irq represents a single bit of
> information. The current implementation is stateless, but in principle it
> could remember its state and ignore redundant calls to qemu_set_irq.
>
> In order to workaround the periodic timer issue, we need some way of for the
> source device to interrogate the target device state relating to this link.
> The suggestions so far are along the lines of "what happened when I made this
> change". This makes me unhappy, because it's overlaying event semantics on top
> of a state based system.
>
> Instead I suggest that we should be describing what the target state
> associated with this input is.  Suitable return values could be:
>  * normal: This input effects the state of the target device. Note that this
> need not imply that changing the input actually effects the output at this
> time. e.g. if an interrupt controller is already processing a higher priority
> input, the low priority inputs should still return "normal" - the input will
> be processed once the unrelated high priority input is finished.
>  * latched: This input has already effected target device state, and will be
> ignored until reset by some external event. Typically means an interrupt
> controller latches its inputs, and this input has already been latched.
>  * masked: This input is ignored.
>
> In practice these should give approximately the same information as event
> based delivered/coalesced/dropped responses.  The difference is that they are
> consistent with the state based nature of qemu_irq.

I agree this would be enough for the current RTC/APIC case.

This doesn't help in EOI handling or message passing in any way, but
we can make completely separate systems for those later when the need
arises.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-13 15:49                 ` Paul Brook
@ 2010-06-13 18:17                   ` Blue Swirl
  2010-06-13 18:39                     ` Paul Brook
  0 siblings, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-13 18:17 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sun, Jun 13, 2010 at 3:49 PM, Paul Brook <paul@codesourcery.com> wrote:
>> I think we could solve all problems (well, maybe not world peace, yet)
>> by switching to message based system for all of DMA and IRQs.
>>
>> Each device would have a message input port and way to output messages.
>>
>> Examples:
>>
>> Zero copy memory access from device D1 to D2 to host memory (D3) with
>> access broken to page length units and errors occurring on the last
>> byte:
>> D1 send_msg(ID, MSG_MEM_WRITE, DMA address, length) -> D2
>>...
>> IRQ delivery chain D1->D2->D3 with coalescing, messages, delivery
>> reporting and EOI:
>> D1 send_msg(ID, MSG_IRQ_RAISE, payload) -> D2
>
> This feels like a terrible idea to me. It introduces an unnecessary RPC
> indirection layer without actually solving any of the problems. It just makes
> it harder (if not impossible) for the compiler to verify any of the interfaces
> between objects.

For the memory access case, in practice the interface could be
sysbus_memory_rw(DeviceState *parent, target_phys_addr_t addr,
target_phys_addr_t size)
in place of send_msg() and
sysbus_memory_rw_cb(DeviceState *dev, void *ptr, size_t size, int status)
in place of send_replymsg() so we'd have compiler type checks.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-13 18:17                   ` Blue Swirl
@ 2010-06-13 18:39                     ` Paul Brook
  2010-06-13 18:54                       ` Blue Swirl
  0 siblings, 1 reply; 44+ messages in thread
From: Paul Brook @ 2010-06-13 18:39 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> On Sun, Jun 13, 2010 at 3:49 PM, Paul Brook <paul@codesourcery.com> wrote:
> >> I think we could solve all problems (well, maybe not world peace, yet)
> >> by switching to message based system for all of DMA and IRQs.
> >> 
> >> Each device would have a message input port and way to output messages.
> >> 
> >> Examples:
> >> 
> >> Zero copy memory access from device D1 to D2 to host memory (D3) with
> >> access broken to page length units and errors occurring on the last
> >> byte:
> >> D1 send_msg(ID, MSG_MEM_WRITE, DMA address, length) -> D2
> >>
> >>...
> >>
> >> IRQ delivery chain D1->D2->D3 with coalescing, messages, delivery
> >> reporting and EOI:
> >> D1 send_msg(ID, MSG_IRQ_RAISE, payload) -> D2
> > 
> > This feels like a terrible idea to me. It introduces an unnecessary RPC
> > indirection layer without actually solving any of the problems. It just
> > makes it harder (if not impossible) for the compiler to verify any of
> > the interfaces between objects.
> 
> For the memory access case, in practice the interface could be
> sysbus_memory_rw(DeviceState *parent, target_phys_addr_t addr,
> target_phys_addr_t size)

Why "parent"?

> in place of send_msg() and
> sysbus_memory_rw_cb(DeviceState *dev, void *ptr, size_t size, int status)
> in place of send_replymsg() so we'd have compiler type checks.

I don't see any point point trying to squeeze this through a common message 
passing API. We *could* do that if we really wanted, but It's a lot of hassle. 
If devices are going to end up using wrappers that look a lot like a straight 
API then what's the point?

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-13 18:39                     ` Paul Brook
@ 2010-06-13 18:54                       ` Blue Swirl
  2010-06-13 19:38                         ` Paul Brook
  0 siblings, 1 reply; 44+ messages in thread
From: Blue Swirl @ 2010-06-13 18:54 UTC (permalink / raw)
  To: Paul Brook
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

On Sun, Jun 13, 2010 at 6:39 PM, Paul Brook <paul@codesourcery.com> wrote:
>> On Sun, Jun 13, 2010 at 3:49 PM, Paul Brook <paul@codesourcery.com> wrote:
>> >> I think we could solve all problems (well, maybe not world peace, yet)
>> >> by switching to message based system for all of DMA and IRQs.
>> >>
>> >> Each device would have a message input port and way to output messages.
>> >>
>> >> Examples:
>> >>
>> >> Zero copy memory access from device D1 to D2 to host memory (D3) with
>> >> access broken to page length units and errors occurring on the last
>> >> byte:
>> >> D1 send_msg(ID, MSG_MEM_WRITE, DMA address, length) -> D2
>> >>
>> >>...
>> >>
>> >> IRQ delivery chain D1->D2->D3 with coalescing, messages, delivery
>> >> reporting and EOI:
>> >> D1 send_msg(ID, MSG_IRQ_RAISE, payload) -> D2
>> >
>> > This feels like a terrible idea to me. It introduces an unnecessary RPC
>> > indirection layer without actually solving any of the problems. It just
>> > makes it harder (if not impossible) for the compiler to verify any of
>> > the interfaces between objects.
>>
>> For the memory access case, in practice the interface could be
>> sysbus_memory_rw(DeviceState *parent, target_phys_addr_t addr,
>> target_phys_addr_t size)
>
> Why "parent"?

Parent device or bus host bridge device. Alternatively there could be
a bus handle.

>> in place of send_msg() and
>> sysbus_memory_rw_cb(DeviceState *dev, void *ptr, size_t size, int status)
>> in place of send_replymsg() so we'd have compiler type checks.
>
> I don't see any point point trying to squeeze this through a common message
> passing API. We *could* do that if we really wanted, but It's a lot of hassle.
> If devices are going to end up using wrappers that look a lot like a straight
> API then what's the point?

Without IRQ and other messages, I agree that at this point it would
not make much sense. Do you think this API as straight implementation
would work? Compared to previous attempts for Generic DMA, we'd avoid
any IO vector splitting/reallocations etc.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-13 18:54                       ` Blue Swirl
@ 2010-06-13 19:38                         ` Paul Brook
  0 siblings, 0 replies; 44+ messages in thread
From: Paul Brook @ 2010-06-13 19:38 UTC (permalink / raw)
  To: Blue Swirl
  Cc: Jan Kiszka, Jan Kiszka, qemu-devel, Gleb Natapov, Juan Quintela

> >> For the memory access case, in practice the interface could be
> >> sysbus_memory_rw(DeviceState *parent, target_phys_addr_t addr,
> >> target_phys_addr_t size)
> > 
> > Why "parent"?
> 
> Parent device or bus host bridge device. Alternatively there could be
> a bus handle.

A device has no way of knowing where that bust host bridge is, and this may be 
the wrong device anyway. The access may be directed at another device on the 
same bus.  A bus handle is trivial to derive this from the device itself.

> > I don't see any point point trying to squeeze this through a common
> > message passing API. We *could* do that if we really wanted, but It's a
> > lot of hassle. If devices are going to end up using wrappers that look a
> > lot like a straight API then what's the point?
> 
> Without IRQ and other messages, I agree that at this point it would
> not make much sense. Do you think this API as straight implementation
> would work? Compared to previous attempts for Generic DMA, we'd avoid
> any IO vector splitting/reallocations etc.

We have already merged a "generic DMA" infrastructure 
(cpu_physical_memory_map). See also dma-helpers.c for code that uses this to 
implement zero-copy transfers to/from block devices.

This is missing code to allow manipulation by intermediate bus/bridges, but I 
believe the basic API is fairly sound. Addition of a device handle or error 
reporting should be possible without requiring major changes to the device 
code.

Paul

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs
  2010-06-13 16:34         ` Paul Brook
  2010-06-13 18:04           ` Blue Swirl
@ 2010-06-14  5:40           ` Gleb Natapov
  1 sibling, 0 replies; 44+ messages in thread
From: Gleb Natapov @ 2010-06-14  5:40 UTC (permalink / raw)
  To: Paul Brook; +Cc: Blue Swirl, Jan Kiszka, Jan Kiszka, qemu-devel, Juan Quintela

On Sun, Jun 13, 2010 at 05:34:24PM +0100, Paul Brook wrote:
> > TBH I preferred the original system whereby the source can query the state
> > of the sink (i.e "are you ignoring this line?").  Note that conceptually
> > this should be *querying* state, not responding to an event.
> 
> People are still pushing qemu_irq as an message passing interface, so I'm 
> going to expand a bit more on how I think this could be avoided.
> 
Please, please, please write code and show how it solves existing
problems. Code talks much better then words.

> Start with the assumption that qemu irq represents a single bit of 
> information. The current implementation is stateless, but in principle it 
> could remember its state and ignore redundant calls to qemu_set_irq.
> 
And I don't see why it will affect proposed implementation. Device
should not call qemu_set_irq() with the same state twice anyway. Some
device's implementations are lazy so they don't track previous state, but
this is just implementation detail. 

> In order to workaround the periodic timer issue, we need some way of for the 
> source device to interrogate the target device state relating to this link. 
> The suggestions so far are along the lines of "what happened when I made this 
> change". This makes me unhappy, because it's overlaying event semantics on top 
> of a state based system.
> 
> Instead I suggest that we should be describing what the target state 
> associated with this input is.  Suitable return values could be:
>  * normal: This input effects the state of the target device. Note that this 
> need not imply that changing the input actually effects the output at this 
> time. e.g. if an interrupt controller is already processing a higher priority 
> input, the low priority inputs should still return "normal" - the input will 
> be processed once the unrelated high priority input is finished.
>  * latched: This input has already effected target device state, and will be 
> ignored until reset by some external event. Typically means an interrupt 
> controller latches its inputs, and this input has already been latched.
>  * masked: This input is ignored.
> 
> In practice these should give approximately the same information as event 
> based delivered/coalesced/dropped responses.  The difference is that they are 
> consistent with the state based nature of qemu_irq.
> 
You just described what was proposed by Jan, you just not agree that it
should be done on top of qemu_irq without proposing any alternatives.
The problem is that device doesn't know what its target is and it can have
multiple targets (that is why hack that exist today works only for one
particular configuration as Blue Swirl found out the hard way). qemu_irq
traverses the dynamic chain of links that connects source and its destinations,
and thus device itself doesn't need to know what its destinations are.

--
			Gleb.

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2010-06-14  5:40 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-06  8:10 [Qemu-devel] [PATCH 00/16] HPET cleanups, fixes, enhancements Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 01/16] hpet: Catch out-of-bounds timer access Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 02/16] hpet: Coding style cleanups and some refactorings Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 03/16] hpet: Silence warning on write to running main counter Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 04/16] hpet: Move static timer field initialization Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 05/16] hpet: Convert to qdev Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 06/16] hpet: Start/stop timer when HPET_TN_ENABLE is modified Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 07/16] monitor/QMP: Drop info hpet / query-hpet Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 08/16] Pass IRQ object on handler invocation Jan Kiszka
2010-06-12 10:31   ` [Qemu-devel] [PATCH v3 " Jan Kiszka
2010-06-06  8:10 ` [Qemu-devel] [PATCH 09/16] Enable message delivery via IRQs Jan Kiszka
2010-06-12 12:21   ` Paul Brook
2010-06-12 12:32     ` Jan Kiszka
2010-06-12 13:44     ` Blue Swirl
2010-06-12 14:15       ` Paul Brook
2010-06-12 14:35         ` Blue Swirl
2010-06-12 15:58           ` Paul Brook
2010-06-12 19:33             ` Blue Swirl
2010-06-12 20:15               ` Paul Brook
2010-06-12 20:32               ` Blue Swirl
2010-06-13  6:47                 ` Blue Swirl
2010-06-13 15:49                 ` Paul Brook
2010-06-13 18:17                   ` Blue Swirl
2010-06-13 18:39                     ` Paul Brook
2010-06-13 18:54                       ` Blue Swirl
2010-06-13 19:38                         ` Paul Brook
2010-06-13 16:34         ` Paul Brook
2010-06-13 18:04           ` Blue Swirl
2010-06-14  5:40           ` Gleb Natapov
2010-06-06  8:10 ` [Qemu-devel] [PATCH 10/16] x86: Refactor RTC IRQ coalescing workaround Jan Kiszka
2010-06-06  8:49   ` [Qemu-devel] " Blue Swirl
2010-06-06  9:06     ` Jan Kiszka
2010-06-06  8:11 ` [Qemu-devel] [PATCH 11/16] hpet/rtc: Rework RTC IRQ replacement by HPET Jan Kiszka
2010-06-06  8:53   ` [Qemu-devel] " Blue Swirl
2010-06-06  9:09     ` Jan Kiszka
2010-06-06  8:11 ` [Qemu-devel] [PATCH 12/16] hpet: Drop static state Jan Kiszka
2010-06-06  8:11 ` [Qemu-devel] [PATCH 13/16] hpet: Add support for level-triggered interrupts Jan Kiszka
2010-06-06  8:11 ` [Qemu-devel] [PATCH 14/16] vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8 Jan Kiszka
2010-06-06  8:11 ` [Qemu-devel] [PATCH 15/16] hpet: Make number of timers configurable Jan Kiszka
2010-06-06  8:11 ` [Qemu-devel] [PATCH 16/16] hpet: Add MSI support Jan Kiszka
2010-06-11 21:31   ` Paul Brook
2010-06-12 10:23     ` [Qemu-devel] [PATCH v3 " Jan Kiszka
2010-06-06  8:56 ` [Qemu-devel] Re: [PATCH 00/16] HPET cleanups, fixes, enhancements Blue Swirl
2010-06-06  9:12   ` Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.