Patchwork qemu_reserve_isa_irq()

login
register
mail settings
Submitter Jes Sorensen
Date Aug. 6, 2009, 1:45 p.m.
Message ID <4A7ADE70.7060204@sgi.com>
Download mbox | patch
Permalink /patch/30845/
State Superseded
Headers show

Comments

Jes Sorensen - Aug. 6, 2009, 1:45 p.m.
Hi

As part of trying to provide the BIOS with information about PCI
interrupt availability, I have added qemu_reserve_isa_irq() to try
and keep track of which IRQs are claimed for ISA.

If we can agree on this approach, then I'll be using it to pass info
on to the guest BIOS in a follow on patch.

Thanks,
Jes
Gleb Natapov - Aug. 7, 2009, 9:13 a.m.
On Thu, Aug 06, 2009 at 03:45:20PM +0200, Jes Sorensen wrote:
> Hi
>
> As part of trying to provide the BIOS with information about PCI
> interrupt availability, I have added qemu_reserve_isa_irq() to try
> and keep track of which IRQs are claimed for ISA.
>
> If we can agree on this approach, then I'll be using it to pass info
> on to the guest BIOS in a follow on patch.
>
Looks good to me. I don't know qdev enough to tell if the same can be done 
as part of qdev infrastructure.

--
			Gleb.
Anthony Liguori - Aug. 10, 2009, 6:57 p.m.
Jes Sorensen wrote:
> Hi
>
> As part of trying to provide the BIOS with information about PCI
> interrupt availability, I have added qemu_reserve_isa_irq() to try
> and keep track of which IRQs are claimed for ISA.
>
> If we can agree on this approach, then I'll be using it to pass info
> on to the guest BIOS in a follow on patch.

Given the new isa qdev support, maybe it would be better to hook into 
isa_connect_irq?

> Thanks,
> Jes
>

Regards,

Anthony Liguori
Jes Sorensen - Aug. 11, 2009, 11:32 a.m.
On 08/10/2009 08:57 PM, Anthony Liguori wrote:
> Jes Sorensen wrote:
>> As part of trying to provide the BIOS with information about PCI
>> interrupt availability, I have added qemu_reserve_isa_irq() to try
>> and keep track of which IRQs are claimed for ISA.
>>
>> If we can agree on this approach, then I'll be using it to pass info
>> on to the guest BIOS in a follow on patch.
>
> Given the new isa qdev support, maybe it would be better to hook into
> isa_connect_irq?

Hi Anthony,

In principle that would be good, the problem is just that the most of
the code still brute force messages with the i8259 array directly,
including the new ISA code. It really needs to be fixed to reference
the ISA IRQ number and not the i8259 array directly :-(

Jes
Gerd Hoffmann - Aug. 11, 2009, 2:08 p.m.
On 08/11/09 13:32, Jes Sorensen wrote:
> On 08/10/2009 08:57 PM, Anthony Liguori wrote:
>> Given the new isa qdev support, maybe it would be better to hook into
>> isa_connect_irq?
>
> Hi Anthony,
>
> In principle that would be good, the problem is just that the most of
> the code still brute force messages with the i8259 array directly,
> including the new ISA code. It really needs to be fixed to reference
> the ISA IRQ number and not the i8259 array directly :-(

How about making isa-bus.c own the i8259 array then?  We could pass it 
to isa_bus_new.  Then switch over to reference isa irqs by number.  That 
allows isa-bus to keep track of the allocations.  Maybe it makes sense 
to kill the sysbus-style isa_{init,connect}_irq split and have a irq bus 
property then.

cheers,
   Gerd
Jes Sorensen - Aug. 11, 2009, 2:45 p.m.
On 08/11/2009 04:08 PM, Gerd Hoffmann wrote:
> On 08/11/09 13:32, Jes Sorensen wrote:
>> In principle that would be good, the problem is just that the most of
>> the code still brute force messages with the i8259 array directly,
>> including the new ISA code. It really needs to be fixed to reference
>> the ISA IRQ number and not the i8259 array directly :-(
>
> How about making isa-bus.c own the i8259 array then? We could pass it to
> isa_bus_new. Then switch over to reference isa irqs by number. That
> allows isa-bus to keep track of the allocations. Maybe it makes sense to
> kill the sysbus-style isa_{init,connect}_irq split and have a irq bus
> property then.

Hi Gerd,

I would like to see that. I was looking into how much it would be, but I
got lost in the qdev dependencies :(

Cheers,
Jes
Gerd Hoffmann - Aug. 11, 2009, 4:16 p.m.
On 08/11/09 16:45, Jes Sorensen wrote:
> I would like to see that. I was looking into how much it would be, but I
> got lost in the qdev dependencies :(

I'll try to have a look tomorrow.

cheers,
   Gerd

Patch

Implement qemu_reserve_isa_irq() and fix the code to call it whenever
an ISA IRQ is claimed.

The old QEMU code simply claimed ISA IRQs without keeping track of it
in any way. This patch tries to catch the culprits and make them call
qemu_reserve_isa_irq() where appropriate.

This allows us to keep track of which IRQs are available for PCI and
later pass that on to the BIOS.

Note that on non PC architectures, this should have zero effect.

Signed-off-by: Jes Sorensen <jes@sgi.com>

---
 hw/cs4231a.c |    3 +++
 hw/gus.c     |    3 +++
 hw/ide.c     |   24 ++++++++++++++++--------
 hw/irq.c     |   12 ++++++++++++
 hw/irq.h     |    2 ++
 hw/pc.c      |   38 ++++++++++++++++++++++++++++++--------
 hw/sb16.c    |    3 +++
 7 files changed, 69 insertions(+), 16 deletions(-)

Index: qemu/hw/cs4231a.c
===================================================================
--- qemu.orig/hw/cs4231a.c
+++ qemu/hw/cs4231a.c
@@ -641,6 +641,9 @@  int cs4231a_init (qemu_irq *pic)
     int i;
     CSState *s;
 
+    if (qemu_reserve_isa_irq(conf.irq))
+        return -1;
+
     s = qemu_mallocz (sizeof (*s));
 
     s->pic = pic;
Index: qemu/hw/gus.c
===================================================================
--- qemu.orig/hw/gus.c
+++ qemu/hw/gus.c
@@ -255,6 +255,9 @@  int GUS_init (qemu_irq *pic)
     GUSState *s;
     struct audsettings as;
 
+    if (qemu_reserve_isa_irq(conf.irq))
+        return -1;
+
     s = qemu_mallocz (sizeof (*s));
 
     AUD_register_card ("gus", &s->card);
Index: qemu/hw/ide.c
===================================================================
--- qemu.orig/hw/ide.c
+++ qemu/hw/ide.c
@@ -3405,10 +3405,14 @@  void pci_piix3_ide_init(PCIBus *bus, Blo
     pci_register_bar((PCIDevice *)d, 4, 0x10,
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
-    ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
-    ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+    if (!qemu_reserve_isa_irq(14)) {
+        ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+        ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+    }
+    if (!qemu_reserve_isa_irq(15)) {
+        ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+        ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+    }
 
     for (i = 0; i < 4; i++)
         if (hd_table[i])
@@ -3445,10 +3449,14 @@  void pci_piix4_ide_init(PCIBus *bus, Blo
     pci_register_bar((PCIDevice *)d, 4, 0x10,
                            PCI_ADDRESS_SPACE_IO, bmdma_map);
 
-    ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
-    ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
-    ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
-    ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+    if (!qemu_reserve_isa_irq(14)) {
+        ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], pic[14]);
+        ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+    }
+    if (!qemu_reserve_isa_irq(15)) {
+        ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], pic[15]);
+        ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+    }
 
     register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
 }
Index: qemu/hw/irq.c
===================================================================
--- qemu.orig/hw/irq.c
+++ qemu/hw/irq.c
@@ -30,6 +30,18 @@  struct IRQState {
     int n;
 };
 
+uint16_t isa_reserved_irqs = 0;
+
+int qemu_reserve_isa_irq(int irq)
+{
+    if (isa_reserved_irqs & (1 << irq)) {
+        fprintf(stderr, "qemu: failed to reserve isa irq %i\n", irq);
+        return -1;
+    }
+    isa_reserved_irqs |= (1 << irq);
+    return 0;
+}
+
 void qemu_set_irq(qemu_irq irq, int level)
 {
     if (!irq)
Index: qemu/hw/irq.h
===================================================================
--- qemu.orig/hw/irq.h
+++ qemu/hw/irq.h
@@ -7,6 +7,8 @@ 
 typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
 typedef void SetIRQFunc(void *opaque, int irq_num, int level);
 
+extern uint16_t isa_reserved_irqs;
+int qemu_reserve_isa_irq(int irq);
 void qemu_set_irq(qemu_irq irq, int level);
 
 static inline void qemu_irq_raise(qemu_irq irq)
Index: qemu/hw/pc.c
===================================================================
--- qemu.orig/hw/pc.c
+++ qemu/hw/pc.c
@@ -1047,10 +1047,14 @@  static void audio_init (PCIBus *pci_bus,
 static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
 {
     static int nb_ne2k = 0;
+    int irq = ne2000_irq[nb_ne2k];
 
     if (nb_ne2k == NE2000_NB_MAX)
         return;
-    isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd);
+    if (qemu_reserve_isa_irq(irq)) {
+        return;
+    }
+    isa_ne2000_init(ne2000_io[nb_ne2k], pic[irq], nd);
     nb_ne2k++;
 }
 
@@ -1271,6 +1275,9 @@  static void pc_init1(ram_addr_t ram_size
 
     cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
     i8259 = i8259_init(cpu_irq[0]);
+    if (qemu_reserve_isa_irq(13)) {
+        exit(1);
+    }
     ferr_irq = i8259[13];
 
     if (pci_enabled) {
@@ -1304,6 +1311,9 @@  static void pc_init1(ram_addr_t ram_size
         }
     }
 
+    if (qemu_reserve_isa_irq(8)) {
+        exit(1);
+    }
     rtc_state = rtc_init(0x70, i8259[8], 2000);
 
     qemu_register_boot_set(pc_boot_set, rtc_state);
@@ -1314,6 +1324,9 @@  static void pc_init1(ram_addr_t ram_size
     if (pci_enabled) {
         ioapic = ioapic_init();
     }
+    if (qemu_reserve_isa_irq(0)) {
+        exit(1);
+    }
     pit = pit_init(0x40, i8259[0]);
     pcspk_init(pit);
     if (!no_hpet) {
@@ -1325,15 +1338,19 @@  static void pc_init1(ram_addr_t ram_size
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(serial_io[i], i8259[serial_irq[i]], 115200,
-                        serial_hds[i]);
+            int irq = serial_irq[i];
+            if (qemu_reserve_isa_irq(irq))
+                break;
+            serial_init(serial_io[i], i8259[irq], 115200, serial_hds[i]);
         }
     }
 
     for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
         if (parallel_hds[i]) {
-            parallel_init(parallel_io[i], i8259[parallel_irq[i]],
-                          parallel_hds[i]);
+            int irq = parallel_irq[i];
+            if (qemu_reserve_isa_irq(irq))
+                break;
+            parallel_init(parallel_io[i], i8259[irq], parallel_hds[i]);
         }
     }
 
@@ -1364,11 +1381,15 @@  static void pc_init1(ram_addr_t ram_size
         pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
     } else {
         for(i = 0; i < MAX_IDE_BUS; i++) {
-            isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
-	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
+            int irq = ide_irq[i];
+            if (!qemu_reserve_isa_irq(irq))
+                isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[irq],
+                             hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
         }
     }
 
+    if (qemu_reserve_isa_irq(1) || qemu_reserve_isa_irq(12))
+        exit(1);
     i8042_init(i8259[1], i8259[12], 0x60);
     DMA_init(0);
 #ifdef HAS_AUDIO
@@ -1379,7 +1400,8 @@  static void pc_init1(ram_addr_t ram_size
         dinfo = drive_get(IF_FLOPPY, 0, i);
         fd[i] = dinfo ? dinfo->bdrv : NULL;
     }
-    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+    if (!qemu_reserve_isa_irq(6))
+        floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
 
Index: qemu/hw/sb16.c
===================================================================
--- qemu.orig/hw/sb16.c
+++ qemu/hw/sb16.c
@@ -1405,6 +1405,9 @@  int SB16_init (qemu_irq *pic)
     static const uint8_t dsp_write_ports[] = {0x6, 0xc};
     static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
 
+    if (qemu_reserve_isa_irq(conf.irq))
+        return -1;
+
     s = qemu_mallocz (sizeof (*s));
 
     s->cmd = -1;