From patchwork Fri Jun 12 01:46:42 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Beth Kon X-Patchwork-Id: 29673 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n5C1kTHj014554 for ; Fri, 12 Jun 2009 01:46:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757622AbZFLBpq (ORCPT ); Thu, 11 Jun 2009 21:45:46 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757420AbZFLBpp (ORCPT ); Thu, 11 Jun 2009 21:45:45 -0400 Received: from e32.co.us.ibm.com ([32.97.110.150]:53019 "EHLO e32.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751103AbZFLBpp (ORCPT ); Thu, 11 Jun 2009 21:45:45 -0400 Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com [9.17.195.106]) by e32.co.us.ibm.com (8.13.1/8.13.1) with ESMTP id n5C1g4kE025579 for ; Thu, 11 Jun 2009 19:42:04 -0600 Received: from d03av03.boulder.ibm.com (d03av03.boulder.ibm.com [9.17.195.169]) by d03relay04.boulder.ibm.com (8.13.8/8.13.8/NCO v9.2) with ESMTP id n5C1jlj5150032 for ; Thu, 11 Jun 2009 19:45:47 -0600 Received: from d03av03.boulder.ibm.com (loopback [127.0.0.1]) by d03av03.boulder.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n5C1jkqh025545 for ; Thu, 11 Jun 2009 19:45:47 -0600 Received: from localhost.localdomain (sig-9-65-123-8.mts.ibm.com [9.65.123.8]) by d03av03.boulder.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n5C1jjdb025531; Thu, 11 Jun 2009 19:45:46 -0600 From: Beth Kon To: avi@redhat.com Cc: kvm@vger.kernel.org, Beth Kon Subject: [PATCH 1/5] Userspace changes for configuring irq0->inti2 override (v6) Date: Thu, 11 Jun 2009 21:46:42 -0400 Message-Id: <1244771206-19872-1-git-send-email-eak@us.ibm.com> X-Mailer: git-send-email 1.5.4.3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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. Changes from v4: - Modify mp_table entry count depending on whether irq_override is enabled. Signed-off-by: Beth Kon --- kvm/bios/rombios32.c | 67 ++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 51 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 diff --git a/kvm/bios/rombios32.c b/kvm/bios/rombios32.c index 7db91d8..d6886ee 100755 --- a/kvm/bios/rombios32.c +++ b/kvm/bios/rombios32.c @@ -446,6 +446,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 @@ -487,6 +490,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; @@ -555,6 +559,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; @@ -1153,7 +1168,14 @@ static void mptable_init(void) putstr(&q, "0.1 "); /* vendor id */ putle32(&q, 0); /* OEM table ptr */ putle16(&q, 0); /* OEM table size */ +#ifdef BX_QEMU + if (irq0_override) + putle16(&q, MAX_CPUS + 17); /* entry count */ + else + putle16(&q, MAX_CPUS + 18); /* entry count */ +#else putle16(&q, MAX_CPUS + 18); /* entry count */ +#endif putle32(&q, 0xfee00000); /* local APIC addr */ putle16(&q, 0); /* ext table length */ putb(&q, 0); /* ext table checksum */ @@ -1197,6 +1219,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 */ @@ -1204,7 +1233,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; @@ -1760,23 +1794,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); @@ -2700,6 +2732,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();