From patchwork Thu Apr 9 22:20:25 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Beth Kon X-Patchwork-Id: 17472 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 n39MKXeR017819 for ; Thu, 9 Apr 2009 22:20:33 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752429AbZDIWU3 (ORCPT ); Thu, 9 Apr 2009 18:20:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1757021AbZDIWU3 (ORCPT ); Thu, 9 Apr 2009 18:20:29 -0400 Received: from e6.ny.us.ibm.com ([32.97.182.146]:40436 "EHLO e6.ny.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752258AbZDIWU2 (ORCPT ); Thu, 9 Apr 2009 18:20:28 -0400 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by e6.ny.us.ibm.com (8.13.1/8.13.1) with ESMTP id n39MM6vv018865 for ; Thu, 9 Apr 2009 18:22:06 -0400 Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay02.pok.ibm.com (8.13.8/8.13.8/NCO v9.2) with ESMTP id n39MKPHP152176 for ; Thu, 9 Apr 2009 18:20:25 -0400 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n39MKPOM013744 for ; Thu, 9 Apr 2009 18:20:25 -0400 Received: from localhost.localdomain (hks.austin.ibm.com [9.3.232.200]) by d01av03.pok.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n39MKO5V013719; Thu, 9 Apr 2009 18:20:24 -0400 From: Beth Kon To: kvm@vger.kernel.org Cc: Beth Kon Subject: [PATCH 2/2] Finish HPET implementation for KVM Date: Thu, 9 Apr 2009 17:20:25 -0500 Message-Id: <1239315625-10101-2-git-send-email-eak@us.ibm.com> X-Mailer: git-send-email 1.5.3.6 In-Reply-To: <1239315625-10101-1-git-send-email-eak@us.ibm.com> References: <1239315625-10101-1-git-send-email-eak@us.ibm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Signed-off-by: Beth Kon --- 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/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl index 06ab25d..84697db 100755 --- a/bios/acpi-dsdt.dsl +++ b/bios/acpi-dsdt.dsl @@ -307,6 +307,24 @@ DefinitionBlock ( ,, , AddressRangeMemory, TypeStatic) }) } + Device(HPET) { + Name(_HID, EISAID("PNP0103")) + Name(_UID, 0) + Method (_STA, 0, NotSerialized) { + Return(0x0F) + } + Name(_CRS, ResourceTemplate() { + DWordMemory( + ResourceConsumer, PosDecode, MinFixed, MaxFixed, + NonCacheable, ReadWrite, + 0x00000000, + 0xFED00000, + 0xFED003FF, + 0x00000000, + 0x00000400 /* 1K memory: FED00000 - FED003FF */ + ) + }) + } } Scope(\_SB.PCI0) { diff --git a/bios/rombios32.c b/bios/rombios32.c index 5cf1f54..959a784 100755 --- a/bios/rombios32.c +++ b/bios/rombios32.c @@ -1275,7 +1275,7 @@ struct rsdp_descriptor /* Root System Descriptor Pointer */ struct rsdt_descriptor_rev1 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ - uint32_t table_offset_entry [2]; /* Array of pointers to other */ + uint32_t table_offset_entry [3]; /* Array of pointers to other */ /* ACPI tables */ } __attribute__((__packed__)); @@ -1415,6 +1415,31 @@ struct madt_processor_apic #endif } __attribute__((__packed__)); +/* + * * ACPI 2.0 Generic Address Space definition. + * */ +struct acpi_20_generic_address { + uint8_t address_space_id; + uint8_t register_bit_width; + uint8_t register_bit_offset; + uint8_t reserved; + uint64_t address; +} __attribute__((__packed__)); + +/* + * * HPET Description Table + * */ +struct acpi_20_hpet { + ACPI_TABLE_HEADER_DEF /* ACPI common table header */ + uint32_t timer_block_id; + struct acpi_20_generic_address addr; + uint8_t hpet_number; + uint16_t min_tick; + uint8_t page_protect; +} __attribute__((__packed__)); + +#define ACPI_HPET_ADDRESS 0xFED00000UL + struct madt_io_apic { APIC_HEADER_DEF @@ -1487,6 +1512,8 @@ void acpi_bios_init(void) struct facs_descriptor_rev1 *facs; struct multiple_apic_table *madt; uint8_t *dsdt; + struct acpi_20_hpet *hpet; + uint32_t hpet_addr; uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr; uint32_t acpi_tables_size, madt_addr, madt_size; int i; @@ -1534,6 +1561,11 @@ void acpi_bios_init(void) madt_size += sizeof(struct madt_intsrcovr); addr += madt_size; + addr = (addr + 7) & ~7; + hpet_addr = addr; + hpet = (void *)(addr); + addr += sizeof(*hpet); + acpi_tables_size = addr - base_addr; BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", @@ -1555,6 +1587,7 @@ void acpi_bios_init(void) memset(rsdt, 0, sizeof(*rsdt)); rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); + rsdt->table_offset_entry[2] = cpu_to_le32(hpet_addr); acpi_build_table_header((struct acpi_table_header *)rsdt, "RSDT", sizeof(*rsdt), 1); @@ -1644,6 +1677,15 @@ void acpi_bios_init(void) } acpi_build_table_header((struct acpi_table_header *)madt, "APIC", madt_size, 1); + /* HPET */ + memset(hpet, 0, sizeof(*hpet)); + /* Note: timer_block_id value must be kept in sync with value + * advertised by emulated hpet in hpet.c + */ + hpet->timer_block_id = cpu_to_le32(0x8086a201); + hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS); + acpi_build_table_header((struct acpi_table_header *)hpet, + "HPET", sizeof(*hpet), 1); } } diff --git a/qemu/hw/hpet.c b/qemu/hw/hpet.c index 7df2d05..2b817a6 100644 --- a/qemu/hw/hpet.c +++ b/qemu/hw/hpet.c @@ -30,6 +30,7 @@ #include "console.h" #include "qemu-timer.h" #include "hpet_emul.h" +#include "qemu-kvm.h" //#define HPET_DEBUG #ifdef HPET_DEBUG @@ -48,6 +49,43 @@ uint32_t hpet_in_legacy_mode(void) return 0; } +static void hpet_kpit_enable(void) +{ + struct kvm_pit_state ps; + kvm_get_pit(kvm_context, &ps); + kvm_set_pit(kvm_context, &ps); +} + +static void hpet_kpit_disable(void) +{ + struct kvm_pit_state ps; + kvm_get_pit(kvm_context, &ps); + ps.channels[0].mode = 0xff; + kvm_set_pit(kvm_context, &ps); +} + +static void hpet_legacy_enable(void) +{ + if (qemu_kvm_pit_in_kernel()) { + hpet_kpit_disable(); + dprintf("qemu: hpet disabled kernel pit\n"); + } else { + hpet_pit_disable(); + dprintf("qemu: hpet disabled userspace pit\n"); + } +} + +static void hpet_legacy_disable(void) +{ + if (qemu_kvm_pit_in_kernel()) { + hpet_kpit_enable(); + dprintf("qemu: hpet enabled kernel pit\n"); + } else { + hpet_pit_enable(); + dprintf("qemu: hpet enabled userspace pit\n"); + } +} + static uint32_t timer_int_route(struct HPETTimer *timer) { uint32_t route; @@ -475,9 +513,9 @@ 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(); + hpet_legacy_enable(); } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) { - hpet_pit_enable(); + hpet_legacy_disable(); } break; case HPET_CFG + 4: @@ -560,7 +598,7 @@ static void hpet_reset(void *opaque) { * hpet_reset is called due to system reset. At this point control must * be returned to pit until SW reenables hpet. */ - hpet_pit_enable(); + hpet_legacy_disable(); count = 1; } diff --git a/qemu/vl.c b/qemu/vl.c index b982b53..d662fba 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -5539,9 +5539,14 @@ int main(int argc, char **argv, char **envp) } if (kvm_enabled()) { - kvm_init_ap(); + kvm_init_ap(); if (kvm_irqchip && !kvm_has_gsi_routing(kvm_context)) { irq0override = 0; + /* if kernel can't do irq routing, interrupt source + * override 0->2 can not be set up as required by hpet, + * so disable hpet. + */ + no_hpet=1; } }