diff mbox

[1/5] BIOS changes for configuring irq0->inti2 override (v4)

Message ID 1244731365-32069-1-git-send-email-eak@us.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Beth Kon June 11, 2009, 2:42 p.m. UTC
These patches resolve the irq0->inti2 override issue, and get the hpet working
on kvm.

Override and HPET changes are sent as a series because HPET depends on the
override. Win2k8 expects the HPET interrupt on inti2, regardless of whether
an override exists in the BIOS. And the HPET spec states that in legacy mode,
timer interrupt is on inti2.

The irq0->inti2 override will always be used unless the kernel cannot do irq
routing (i.e., compatibility with old kernels). So if the kernel is capable,
userspace sets up irq0->inti2 via the irq routing interface, and adds the
irq0->inti2 override to the MADT interrupt source override table,
and the mp table (for the no-acpi case).

Changes from v3:

- changes based on comments from Avi and Gleb.
- corrected legacy enable/disable for in-kernel PIT. The code now best
  approximates a multiplexer that disables PIT interrupts when HPET is 
  in legacy mode (as described by HPET spec). Any changes to the PIT that 
  may occur while HPET is operating in legacy mode are saved, so if 
  HPET leaves legacy mode, the PIT is just reenabled, with mode set     
  to whatever the last setting from guest was. Legacy mode is disabled
  at least during crash and shutdown (in Linux), so this needs to be 
  handled properly.


---
 kvm/bios/rombios32.c |   60 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 44 insertions(+), 16 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Sebastian Herbszt June 11, 2009, 8:50 p.m. UTC | #1
Beth Kon wrote:
> These patches resolve the irq0->inti2 override issue, and get the hpet working
> on kvm.
> 
> Override and HPET changes are sent as a series because HPET depends on the
> override. Win2k8 expects the HPET interrupt on inti2, regardless of whether
> an override exists in the BIOS. And the HPET spec states that in legacy mode,
> timer interrupt is on inti2.
> 
> The irq0->inti2 override will always be used unless the kernel cannot do irq
> routing (i.e., compatibility with old kernels). So if the kernel is capable,
> userspace sets up irq0->inti2 via the irq routing interface, and adds the
> irq0->inti2 override to the MADT interrupt source override table,
> and the mp table (for the no-acpi case).
> 
> Changes from v3:
> 
> - changes based on comments from Avi and Gleb.
> - corrected legacy enable/disable for in-kernel PIT. The code now best
>  approximates a multiplexer that disables PIT interrupts when HPET is 
>  in legacy mode (as described by HPET spec). Any changes to the PIT that 
>  may occur while HPET is operating in legacy mode are saved, so if 
>  HPET leaves legacy mode, the PIT is just reenabled, with mode set     
>  to whatever the last setting from guest was. Legacy mode is disabled
>  at least during crash and shutdown (in Linux), so this needs to be 
>  handled properly.
> 
> 
> ---
> kvm/bios/rombios32.c |   60 ++++++++++++++++++++++++++++++++++++-------------
> 1 files changed, 44 insertions(+), 16 deletions(-)

What about the mptable entry count?
Think it would need something like

#ifdef BX_QEMU
  if (irq0_override)
    putle16(&q, smp_cpus + 17); /* entry count */
  else
    putle16(&q, smp_cpus + 18); /* entry count */
#else
  putle16(&q, smp_cpus + 18); /* entry count */
#endif

Your patch "Fix non-ACPI Timer Interrupt Routing - v3" [1] included such a change.

[1] http://lists.gnu.org/archive/html/qemu-devel/2009-04/msg01396.html

- Sebastian

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Beth Kon June 11, 2009, 9:23 p.m. UTC | #2
Sebastian Herbszt wrote:
> Beth Kon wrote:
>> These patches resolve the irq0->inti2 override issue, and get the 
>> hpet working
>> on kvm.
>>
>> Override and HPET changes are sent as a series because HPET depends 
>> on the
>> override. Win2k8 expects the HPET interrupt on inti2, regardless of 
>> whether
>> an override exists in the BIOS. And the HPET spec states that in 
>> legacy mode,
>> timer interrupt is on inti2.
>>
>> The irq0->inti2 override will always be used unless the kernel cannot 
>> do irq
>> routing (i.e., compatibility with old kernels). So if the kernel is 
>> capable,
>> userspace sets up irq0->inti2 via the irq routing interface, and adds 
>> the
>> irq0->inti2 override to the MADT interrupt source override table,
>> and the mp table (for the no-acpi case).
>>
>> Changes from v3:
>>
>> - changes based on comments from Avi and Gleb.
>> - corrected legacy enable/disable for in-kernel PIT. The code now best
>>  approximates a multiplexer that disables PIT interrupts when HPET is 
>>  in legacy mode (as described by HPET spec). Any changes to the PIT 
>> that  may occur while HPET is operating in legacy mode are saved, so 
>> if  HPET leaves legacy mode, the PIT is just reenabled, with mode 
>> set      to whatever the last setting from guest was. Legacy mode is 
>> disabled
>>  at least during crash and shutdown (in Linux), so this needs to be 
>>  handled properly.
>>
>>
>> ---
>> kvm/bios/rombios32.c |   60 
>> ++++++++++++++++++++++++++++++++++++-------------
>> 1 files changed, 44 insertions(+), 16 deletions(-)
>
> What about the mptable entry count?
> Think it would need something like
>
> #ifdef BX_QEMU
>  if (irq0_override)
>    putle16(&q, smp_cpus + 17); /* entry count */
>  else
>    putle16(&q, smp_cpus + 18); /* entry count */
> #else
>  putle16(&q, smp_cpus + 18); /* entry count */
> #endif
>
> Your patch "Fix non-ACPI Timer Interrupt Routing - v3" [1] included 
> such a change.
>
> [1] http://lists.gnu.org/archive/html/qemu-devel/2009-04/msg01396.html
Yes, I lost that somehow! Thanks (again!).

>
> - Sebastian
>

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Beth Kon June 11, 2009, 9:46 p.m. UTC | #3
Beth Kon wrote:
> Sebastian Herbszt wrote:
>> Beth Kon wrote:
>>> These patches resolve the irq0->inti2 override issue, and get the 
>>> hpet working
>>> on kvm.
>>>
>>> Override and HPET changes are sent as a series because HPET depends 
>>> on the
>>> override. Win2k8 expects the HPET interrupt on inti2, regardless of 
>>> whether
>>> an override exists in the BIOS. And the HPET spec states that in 
>>> legacy mode,
>>> timer interrupt is on inti2.
>>>
>>> The irq0->inti2 override will always be used unless the kernel 
>>> cannot do irq
>>> routing (i.e., compatibility with old kernels). So if the kernel is 
>>> capable,
>>> userspace sets up irq0->inti2 via the irq routing interface, and 
>>> adds the
>>> irq0->inti2 override to the MADT interrupt source override table,
>>> and the mp table (for the no-acpi case).
>>>
>>> Changes from v3:
>>>
>>> - changes based on comments from Avi and Gleb.
>>> - corrected legacy enable/disable for in-kernel PIT. The code now best
>>>  approximates a multiplexer that disables PIT interrupts when HPET 
>>> is  in legacy mode (as described by HPET spec). Any changes to the 
>>> PIT that  may occur while HPET is operating in legacy mode are 
>>> saved, so if  HPET leaves legacy mode, the PIT is just reenabled, 
>>> with mode set      to whatever the last setting from guest was. 
>>> Legacy mode is disabled
>>>  at least during crash and shutdown (in Linux), so this needs to be 
>>>  handled properly.
>>>
>>>
>>> ---
>>> kvm/bios/rombios32.c |   60 
>>> ++++++++++++++++++++++++++++++++++++-------------
>>> 1 files changed, 44 insertions(+), 16 deletions(-)
>>
>> What about the mptable entry count?
>> Think it would need something like
>>
>> #ifdef BX_QEMU
>>  if (irq0_override)
>>    putle16(&q, smp_cpus + 17); /* entry count */
>>  else
>>    putle16(&q, smp_cpus + 18); /* entry count */
>> #else
>>  putle16(&q, smp_cpus + 18); /* entry count */
>> #endif
>>
>> Your patch "Fix non-ACPI Timer Interrupt Routing - v3" [1] included 
>> such a change.
>>
>> [1] http://lists.gnu.org/archive/html/qemu-devel/2009-04/msg01396.html
> Yes, I lost that somehow! Thanks (again!).
Actually, it isn't that simple. That patch that you referred to was a 
qemu patch. But I still don't see it in qemu-patched bochs bios. 
Apparently, I did neglect to add it to the kvm bios patches that I had 
waiting.

Anthony, do you know what happened to this patch?
>
>>
>> - Sebastian
>>
>
> -- 
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/kvm/bios/rombios32.c b/kvm/bios/rombios32.c
index 369cbef..9d6910e 100755
--- a/kvm/bios/rombios32.c
+++ b/kvm/bios/rombios32.c
@@ -444,6 +444,9 @@  uint32_t cpuid_features;
 uint32_t cpuid_ext_features;
 unsigned long ram_size;
 uint64_t ram_end;
+#ifdef BX_QEMU
+uint8_t irq0_override;
+#endif
 #ifdef BX_USE_EBDA_TABLES
 unsigned long ebda_cur_addr;
 #endif
@@ -485,6 +488,7 @@  void wrmsr_smp(uint32_t index, uint64_t val)
 #define QEMU_CFG_ARCH_LOCAL     0x8000
 #define QEMU_CFG_ACPI_TABLES  (QEMU_CFG_ARCH_LOCAL + 0)
 #define QEMU_CFG_SMBIOS_ENTRIES  (QEMU_CFG_ARCH_LOCAL + 1)
+#define QEMU_CFG_IRQ0_OVERRIDE   (QEMU_CFG_ARCH_LOCAL + 2)
 
 int qemu_cfg_port;
 
@@ -553,6 +557,17 @@  uint64_t qemu_cfg_get64 (void)
 }
 #endif
 
+#ifdef BX_QEMU
+void irq0_override_probe(void)
+{
+    if(qemu_cfg_port) {
+        qemu_cfg_select(QEMU_CFG_IRQ0_OVERRIDE);
+        qemu_cfg_read(&irq0_override, 1);
+        return;
+    }
+}
+#endif
+
 void cpu_probe(void)
 {
     uint32_t eax, ebx, ecx, edx;
@@ -1195,6 +1210,13 @@  static void mptable_init(void)
 
     /* irqs */
     for(i = 0; i < 16; i++) {
+#ifdef BX_QEMU
+        /* One entry per ioapic interrupt destination. Destination 2 is covered
+         * by irq0->inti2 override (i == 0). Source IRQ 2 is unused
+         */
+        if (irq0_override && i == 2)
+            continue;
+#endif
         putb(&q, 3); /* entry type = I/O interrupt */
         putb(&q, 0); /* interrupt type = vectored interrupt */
         putb(&q, 0); /* flags: po=0, el=0 */
@@ -1202,7 +1224,12 @@  static void mptable_init(void)
         putb(&q, 0); /* source bus ID = ISA */
         putb(&q, i); /* source bus IRQ */
         putb(&q, ioapic_id); /* dest I/O APIC ID */
-        putb(&q, i); /* dest I/O APIC interrupt in */
+#ifdef BX_QEMU
+        if (irq0_override && i == 0)
+            putb(&q, 2); /* dest I/O APIC interrupt in */
+        else
+#endif
+            putb(&q, i); /* dest I/O APIC interrupt in */
     }
     /* patch length */
     len = q - mp_config_table;
@@ -1758,23 +1785,21 @@  void acpi_bios_init(void)
         io_apic->io_apic_id = smp_cpus;
         io_apic->address = cpu_to_le32(0xfec00000);
         io_apic->interrupt = cpu_to_le32(0);
-#ifdef BX_QEMU
-#ifdef HPET_WORKS_IN_KVM
         io_apic++;
-
-        int_override = (void *)io_apic;
-        int_override->type = APIC_XRUPT_OVERRIDE;
-        int_override->length = sizeof(*int_override);
-        int_override->bus = cpu_to_le32(0);
-        int_override->source = cpu_to_le32(0);
-        int_override->gsi = cpu_to_le32(2);
-        int_override->flags = cpu_to_le32(0);
-#endif
+        int_override = (struct madt_int_override*)(io_apic);
+#ifdef BX_QEMU
+        if (irq0_override) {
+            memset(int_override, 0, sizeof(*int_override));
+            int_override->type = APIC_XRUPT_OVERRIDE;
+            int_override->length = sizeof(*int_override);
+            int_override->source = 0;
+            int_override->gsi = 2;
+            int_override->flags = 0; /* conforms to bus specifications */
+            int_override++;
+        }
 #endif
-
-        int_override = (struct madt_int_override*)(io_apic + 1);
-        for ( i = 0; i < 16; i++ ) {
-            if ( PCI_ISA_IRQ_MASK & (1U << i) ) {
+        for (i = 0; i < 16; i++) {
+            if (PCI_ISA_IRQ_MASK & (1U << i)) {
                 memset(int_override, 0, sizeof(*int_override));
                 int_override->type   = APIC_XRUPT_OVERRIDE;
                 int_override->length = sizeof(*int_override);
@@ -2697,6 +2722,9 @@  void rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag)
 
     if (bios_table_cur_addr != 0) {
 
+#ifdef BX_QEMU
+        irq0_override_probe();
+#endif
         mptable_init();
 
         smbios_init();