diff mbox

[57/61] ioapic: add callback when entry is set or ioapic is reset

Message ID 1254305917-14784-58-git-send-email-yamahata@valinux.co.jp
State Superseded
Headers show

Commit Message

Isaku Yamahata Sept. 30, 2009, 10:18 a.m. UTC
Add hooks to ioapic.
This is necessary for pci interrupt routing mode from
PIC mode to IO APIC mode.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
 hw/ioapic.c |   20 +++++++++++++++++++-
 hw/pc.h     |    2 ++
 2 files changed, 21 insertions(+), 1 deletions(-)

Comments

Gleb Natapov Oct. 1, 2009, 1:37 p.m. UTC | #1
On Wed, Sep 30, 2009 at 07:18:33PM +0900, Isaku Yamahata wrote:
> Add hooks to ioapic.
> This is necessary for pci interrupt routing mode from
> PIC mode to IO APIC mode.
According to my very brief looking at ICH9 spec switching from PIC mode
to IO APIC mode is done separately for each PIRQ by setting bit 7 of
PIRQ[n]_ROUT register to 1. This callback looks completely out of place.

> 
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
> ---
>  hw/ioapic.c |   20 +++++++++++++++++++-
>  hw/pc.h     |    2 ++
>  2 files changed, 21 insertions(+), 1 deletions(-)
> 
> diff --git a/hw/ioapic.c b/hw/ioapic.c
> index a9a8e00..882ca9d 100644
> --- a/hw/ioapic.c
> +++ b/hw/ioapic.c
> @@ -53,8 +53,16 @@ struct IOAPICState {
>  
>      uint32_t irr;
>      uint64_t ioredtbl[IOAPIC_NUM_PINS];
> +    ioapic_update_fn update_fn;
> +    void *opaque;
>  };
>  
> +static void ioapic_callback(IOAPICState *s, int reset)
> +{
> +    if (s->update_fn)
> +        s->update_fn(s->opaque, reset);
> +}
> +
>  static void ioapic_service(IOAPICState *s)
>  {
>      uint8_t i;
> @@ -186,6 +194,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
>                          s->ioredtbl[index] &= ~0xffffffffULL;
>                          s->ioredtbl[index] |= val;
>                      }
> +                    ioapic_callback(s, 0);
>                      ioapic_service(s);
>                  }
>          }
> @@ -210,6 +219,8 @@ static void ioapic_reset(void *opaque)
>      IOAPICState *s = opaque;
>      int i;
>  
> +    ioapic_callback(s, 1);
> +
>      memset(s, 0, sizeof(*s));
>      for(i = 0; i < IOAPIC_NUM_PINS; i++)
>          s->ioredtbl[i] = 1 << 16; /* mask LVT */
> @@ -227,13 +238,15 @@ static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
>      ioapic_mem_writel,
>  };
>  
> -qemu_irq *ioapic_init(void)
> +qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
>  {
>      IOAPICState *s;
>      qemu_irq *irq;
>      int io_memory;
>  
>      s = qemu_mallocz(sizeof(IOAPICState));
> +    s->update_fn = update_fn;
> +    s->opaque = opaque;
>      ioapic_reset(s);
>  
>      io_memory = cpu_register_io_memory(ioapic_mem_read,
> @@ -246,3 +259,8 @@ qemu_irq *ioapic_init(void)
>  
>      return irq;
>  }
> +
> +qemu_irq *ioapic_init(void)
> +{
> +    return ioapic_init_with_arg(NULL, NULL);
> +}
> diff --git a/hw/pc.h b/hw/pc.h
> index 7577956..44eac49 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -52,6 +52,8 @@ 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);
> +typedef void (*ioapic_update_fn)(void *opaque, int reset);
> +qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque);
>  void apic_reset_irq_delivered(void);
>  int apic_get_irq_delivered(void);
>  
> -- 
> 1.6.0.2
> 
> 

--
			Gleb.
Avi Kivity Oct. 1, 2009, 4:04 p.m. UTC | #2
On 10/01/2009 03:37 PM, Gleb Natapov wrote:
> On Wed, Sep 30, 2009 at 07:18:33PM +0900, Isaku Yamahata wrote:
>    
>> Add hooks to ioapic.
>> This is necessary for pci interrupt routing mode from
>> PIC mode to IO APIC mode.
>>      
> According to my very brief looking at ICH9 spec switching from PIC mode
> to IO APIC mode is done separately for each PIRQ by setting bit 7 of
> PIRQ[n]_ROUT register to 1. This callback looks completely out of place.
>    

Disassembling the _PIC and _PRT methods of a Q35 machine will probably 
yield how this is done on real hardware.
diff mbox

Patch

diff --git a/hw/ioapic.c b/hw/ioapic.c
index a9a8e00..882ca9d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -53,8 +53,16 @@  struct IOAPICState {
 
     uint32_t irr;
     uint64_t ioredtbl[IOAPIC_NUM_PINS];
+    ioapic_update_fn update_fn;
+    void *opaque;
 };
 
+static void ioapic_callback(IOAPICState *s, int reset)
+{
+    if (s->update_fn)
+        s->update_fn(s->opaque, reset);
+}
+
 static void ioapic_service(IOAPICState *s)
 {
     uint8_t i;
@@ -186,6 +194,7 @@  static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
                         s->ioredtbl[index] &= ~0xffffffffULL;
                         s->ioredtbl[index] |= val;
                     }
+                    ioapic_callback(s, 0);
                     ioapic_service(s);
                 }
         }
@@ -210,6 +219,8 @@  static void ioapic_reset(void *opaque)
     IOAPICState *s = opaque;
     int i;
 
+    ioapic_callback(s, 1);
+
     memset(s, 0, sizeof(*s));
     for(i = 0; i < IOAPIC_NUM_PINS; i++)
         s->ioredtbl[i] = 1 << 16; /* mask LVT */
@@ -227,13 +238,15 @@  static CPUWriteMemoryFunc * const ioapic_mem_write[3] = {
     ioapic_mem_writel,
 };
 
-qemu_irq *ioapic_init(void)
+qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque)
 {
     IOAPICState *s;
     qemu_irq *irq;
     int io_memory;
 
     s = qemu_mallocz(sizeof(IOAPICState));
+    s->update_fn = update_fn;
+    s->opaque = opaque;
     ioapic_reset(s);
 
     io_memory = cpu_register_io_memory(ioapic_mem_read,
@@ -246,3 +259,8 @@  qemu_irq *ioapic_init(void)
 
     return irq;
 }
+
+qemu_irq *ioapic_init(void)
+{
+    return ioapic_init_with_arg(NULL, NULL);
+}
diff --git a/hw/pc.h b/hw/pc.h
index 7577956..44eac49 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -52,6 +52,8 @@  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);
+typedef void (*ioapic_update_fn)(void *opaque, int reset);
+qemu_irq *ioapic_init_with_arg(ioapic_update_fn update_fn, void *opaque);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);