From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MWsji-0002FJ-I1 for qemu-devel@nongnu.org; Fri, 31 Jul 2009 10:05:30 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MWsjc-0002C8-FR for qemu-devel@nongnu.org; Fri, 31 Jul 2009 10:05:29 -0400 Received: from [199.232.76.173] (port=43506 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MWsjc-0002Bz-6G for qemu-devel@nongnu.org; Fri, 31 Jul 2009 10:05:24 -0400 Received: from e7.ny.us.ibm.com ([32.97.182.137]:37539) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1MWsjb-0006tR-K1 for qemu-devel@nongnu.org; Fri, 31 Jul 2009 10:05:23 -0400 Received: from d01relay04.pok.ibm.com (d01relay04.pok.ibm.com [9.56.227.236]) by e7.ny.us.ibm.com (8.14.3/8.13.1) with ESMTP id n6VE4upc027793 for ; Fri, 31 Jul 2009 10:04:56 -0400 Received: from d01av02.pok.ibm.com (d01av02.pok.ibm.com [9.56.224.216]) by d01relay04.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id n6VE5ISg220160 for ; Fri, 31 Jul 2009 10:05:18 -0400 Received: from d01av02.pok.ibm.com (loopback [127.0.0.1]) by d01av02.pok.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n6VE2akA026914 for ; Fri, 31 Jul 2009 10:02:36 -0400 From: Beth Kon Date: Fri, 31 Jul 2009 10:06:01 -0400 Message-Id: <1249049162-685-1-git-send-email-eak@us.ibm.com> Subject: [Qemu-devel] [PATCH 1/2] Make HPET Legacy Only List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Beth Kon Because of unavailability of IOAPIC interrupt lines, HPET currently supports only legacy mode, where the legacy timer interrupt (inti2) is used. This patch makes this explicit by reducing the number of timers supported by HPET to 2 (the 2 legacy timers) and advertising no available IOAPIC interrupt lines. This patch also adds a check, suggested by Andriy Gapon, to ensure that the interrupt chosen by the guest is one of those advertised by the HPET as available. This is currently a noop since HPET advertises none as available, but in the event of future expansion and availability of IOAPIC interrupt lines, or implementation of level-triggered interrupts that can share interrupt lines, this code will be in place. This subset of HPET capability (legacy-only) is reasonable, since the basic operation of linux and windows only uses the HPET in legacy mode, at least that's what all my testing so far has shown. Only userspace access to the hpet would use non-legacy timers. diff --git a/hw/hpet.c b/hw/hpet.c index 01b10aa..56fa27c 100644 --- a/hw/hpet.c +++ b/hw/hpet.c @@ -47,12 +47,16 @@ uint32_t hpet_in_legacy_mode(void) return 0; } -static uint32_t timer_int_route(struct HPETTimer *timer) -{ - uint32_t route; - route = (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT; - return route; -} +/* future code for when non-legacy interrupts are supported + * (when spare ioapic interrupts are available) + * static uint32_t timer_int_route(struct HPETTimer *timer) + * { + * uint32_t route; + * route = (timer->config & HPET_TN_INT_ROUTE_CNF_MASK) + * >> HPET_TN_INT_ROUTE_CNF_SHIFT; + * return route; + *} + */ static uint32_t hpet_enabled(void) { @@ -137,7 +141,6 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current) static void update_irq(struct HPETTimer *timer) { qemu_irq irq; - int route; if (timer->tn <= 1 && hpet_in_legacy_mode()) { /* if LegacyReplacementRoute bit is set, HPET specification requires @@ -149,8 +152,15 @@ static void update_irq(struct HPETTimer *timer) } else irq=timer->state->irqs[8]; } else { - route=timer_int_route(timer); - irq=timer->state->irqs[route]; + /* hpet implementation does not currently support + * non-legacy interrupts due to unavailability of + * IOAPIC interrupts */ + printf("qemu: hpet only supports legacy interrupts\n"); + exit (-1); + /* future code for when non-legacy interrupts are supported + * replace above printf and exit with 2 lines below + * route=timer_int_route(timer); + * irq=timer->state->irqs[route]; */ } if (timer_enabled(timer) && hpet_enabled()) { qemu_irq_pulse(irq); @@ -372,6 +382,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr, int i; HPETState *s = (HPETState *)opaque; uint64_t old_val, new_val, val, index; + uint32_t route_cap, route_req; dprintf("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value); index = addr; @@ -388,6 +399,14 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr, case HPET_TN_CFG: dprintf("qemu: hpet_ram_writel HPET_TN_CFG\n"); val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK); + route_cap = timer->config >> 32; + route_req = (val & HPET_TN_INT_ROUTE_CNF_MASK) >> + HPET_TN_INT_ROUTE_CNF_SHIFT; + /* check if requested route is included in advertised + * route capabilities. If not, set route cnf to 0 */ + if (!((route_cap >> route_req) & 1)) { + val = val & ~HPET_TN_INT_ROUTE_CNF_MASK; + } timer->config = (timer->config & 0xffffffff00000000ULL) | val; if (new_val & HPET_TN_32BIT) { timer->cmp = (uint32_t)timer->cmp; @@ -542,7 +561,7 @@ static void hpet_reset(void *opaque) { timer->cmp = ~0ULL; timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP; /* advertise availability of ioapic inti2 */ - timer->config |= 0x00000004ULL << 32; + timer->config |= HPET_TN_INT_ROUTE_CAP << 32; timer->state = s; timer->period = 0ULL; timer->wrap_flag = 0; @@ -550,8 +569,8 @@ static void hpet_reset(void *opaque) { s->hpet_counter = 0ULL; s->hpet_offset = 0ULL; - /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */ - s->capability = 0x8086a201ULL; + /* 64-bit main counter; 2 timers supported; LegacyReplacementRoute. */ + s->capability = 0x8086a101ULL; s->capability |= ((HPET_CLK_PERIOD) << 32); s->config = 0ULL; if (count > 0) diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h index 3258d8b..d7233aa 100644 --- a/hw/hpet_emul.h +++ b/hw/hpet_emul.h @@ -17,7 +17,7 @@ #define HPET_CLK_PERIOD 10000000ULL /* 10000000 femtoseconds == 10ns*/ #define FS_PER_NS 1000000 -#define HPET_NUM_TIMERS 3 +#define HPET_NUM_TIMERS 2 #define HPET_TIMER_TYPE_LEVEL 0x002 #define HPET_CFG_ENABLE 0x001 @@ -40,10 +40,12 @@ #define HPET_TN_SIZE_CAP 0x020 #define HPET_TN_SETVAL 0x040 #define HPET_TN_32BIT 0x100 -#define HPET_TN_INT_ROUTE_MASK 0x3e00 -#define HPET_TN_CFG_WRITE_MASK 0x3f4e -#define HPET_TN_INT_ROUTE_SHIFT 9 +#define HPET_TN_INT_ENB_CNF_MASK 0x004 +#define HPET_TN_INT_ROUTE_CNF_MASK 0x3e00 +#define HPET_TN_INT_ROUTE_CNF_SHIFT 9 +#define HPET_TN_INT_ROUTE_CAP 0x00000000ULL /* ioapic interrupts available for hpet non-legacy use */ #define HPET_TN_INT_ROUTE_CAP_SHIFT 32 +#define HPET_TN_CFG_WRITE_MASK 0x3f4e #define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U struct HPETState;