* [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
@ 2008-08-02 11:05 Beth Kon
2008-08-02 11:38 ` Samuel Thibault
2008-08-02 11:42 ` Paul Brook
0 siblings, 2 replies; 7+ messages in thread
From: Beth Kon @ 2008-08-02 11:05 UTC (permalink / raw)
To: qemu-devel; +Cc: Beth Kon, Alexander Graf, kvm
Major changes:
- Rebased to register-based operations for ease of save/restore.
- Looked through Xen's hpet implementation and picked up a bunch of
things, though not quite everything yet. Thanks!
- PIT and RTC are entirely disabled in legacy mode, not just their
interrupts.
There is still a bunch to do but I'm re-posting primarily because
of the switch to register-based. I have still only tested with a
linux guest. Windows guest is next on my list... as soon as I return
from my week vacation.
I've been playing with CONFIG_NO_HZ and been surprised by the
results. I was trying to reproduce the wakeup every 10ms that
Samuel Thibault mentioned, thinking the HPET would improve it.
But for an idle guest in both cases (with and without HPET), the
number of wakeups per second was relatively low (28). Ultimately
this depends on exactly what the guest is doing
when idle, so maybe the HPET won't provide any improvement here.
But in any case, I didn't see the 10ms wakeup cycle with CONFIG_NO_HZ.
If anyone can shed any light on this, I could look into it more if need
be.
Signed-off-by: Beth Kon <eak@us.ibm.com>
***
Makefile.target | 2
hw/hpet.c | 441 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/i8254.c | 11 +
hw/mc146818rtc.c | 30 +++
hw/pc.c | 2
5 files changed, 483 insertions(+), 3 deletions(-)
***
diff --git a/Makefile.target b/Makefile.target
index 42162c3..946bdef 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -536,7 +536,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
-OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o
+OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
diff --git a/hw/hpet.c b/hw/hpet.c
new file mode 100644
index 0000000..adfecf0
--- /dev/null
+++ b/hw/hpet.c
@@ -0,0 +1,441 @@
+/*
+ * High Precisition Event Timer emulation
+ *
+ * Copyright (c) 2007 Alexander Graf
+ * Copyright (c) 2008 IBM Corporation
+ *
+ * Authors: Beth Kon <bkon@us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * *****************************************************************
+ *
+ * This driver attempts to emulate an HPET device in software. It is by no
+ * means complete and is prone to break on certain conditions.
+ *
+ */
+#include "hw.h"
+#include "console.h"
+#include "qemu-timer.h"
+
+//#define HPET_DEBUG
+
+#define HPET_BASE 0xfed00000
+#define HPET_CLK_PERIOD 10000000ULL /* 10000000 femtoseconds == 10ns*/
+
+#define FS_PER_NS 1000000
+#define HPET_NUM_TIMERS 3
+#define HPET_TIMER_TYPE_LEVEL 1
+#define HPET_TIMER_TYPE_EDGE 0
+#define HPET_TIMER_DELIVERY_APIC 0
+#define HPET_TIMER_DELIVERY_FSB 1
+#define HPET_TIMER_CAP_FSB_INT_DEL (1 << 15)
+#define HPET_TIMER_CAP_PER_INT (1 << 4)
+
+#define HPET_CFG_ENABLE 0x001
+#define HPET_CFG_LEGACY 0x002
+
+#define HPET_ID 0x000
+#define HPET_PERIOD 0x004
+#define HPET_CFG 0x010
+#define HPET_STATUS 0x020
+#define HPET_COUNTER 0x0f0
+#define HPET_TN_REGS 0x100 ... 0x3ff /*address range of all TN regs*/
+#define HPET_TN_CFG 0x000
+#define HPET_TN_CMP 0x008
+#define HPET_TN_ROUTE 0x010
+
+
+#define HPET_TN_INT_TYPE_LEVEL 0x002
+#define HPET_TN_ENABLE 0x004
+#define HPET_TN_PERIODIC 0x008
+#define HPET_TN_PERIODIC_CAP 0x010
+#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_INT_ROUTE_SHIFT 9
+#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
+#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
+
+#define timer_int_route(timer) \
+ ((timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT)
+
+#define hpet_enabled(s) (s->config & HPET_CFG_ENABLE)
+#define timer_is_periodic(t) (t->config & HPET_TN_PERIODIC)
+#define timer_enabled(t) (t->config & HPET_TN_ENABLE)
+
+struct HPETState;
+typedef struct HPETTimer { /* timers */
+ uint8_t tn; /*timer number*/
+ QEMUTimer *qemu_timer;
+ struct HPETState *state;
+ /* Memory-mapped, software visible timer registers */
+ uint64_t config; /* configuration/cap */
+ uint64_t cmp; /* comparator */
+ uint64_t fsb; /* FSB route, not supported now */
+ /* Hidden register state */
+ uint64_t period; /* Last value written to comparator */
+} HPETTimer;
+
+
+typedef struct HPETState {
+ uint64_t hpet_offset;
+ qemu_irq *irqs;
+ HPETTimer timer[HPET_NUM_TIMERS];
+ /* Memory-mapped, software visible registers */
+ uint64_t capability; /* capabilities */
+ uint64_t config; /* configuration */
+ uint64_t isr; /* interrupt status reg */
+ uint64_t hpet_counter; /* main counter */
+} HPETState;
+
+
+
+int hpet_legacy=0;
+
+static void update_irq(struct HPETTimer *timer)
+{
+ qemu_irq irq;
+ int route;
+
+ if ( (timer->tn <= 1) && (timer->state->config & HPET_CFG_LEGACY) ) {
+
+ /* if LegacyReplacementRoute bit is set, HPET specification requires
+ * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
+ * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
+ */
+ if (timer->tn == 0)
+ irq=timer->state->irqs[0];
+ else
+ irq=timer->state->irqs[8];
+ }else{
+ route=timer_int_route(timer);
+ irq=timer->state->irqs[route];
+ }
+
+ if(timer_enabled(timer) && hpet_enabled(timer->state)) {
+ qemu_irq_pulse(irq);
+ }
+}
+
+static inline uint64_t ticks_to_ns(uint64_t value)
+{
+ return (value * HPET_CLK_PERIOD / FS_PER_NS);
+}
+
+static inline uint64_t ns_to_ticks(uint64_t value)
+{
+ return (value * FS_PER_NS / HPET_CLK_PERIOD);
+}
+
+static inline uint64_t hpet_fixup_reg(
+ uint64_t new, uint64_t old, uint64_t mask)
+{
+ new &= mask;
+ new |= old & ~mask;
+ return new;
+}
+
+static void hpet_timer(void *opaque)
+{
+ HPETTimer *t = (HPETTimer*)opaque;
+ if(t->config & HPET_TN_PERIODIC) {
+ t->cmp += t->period;
+ qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
+ + ticks_to_ns(t->period));
+ }
+ update_irq(t);
+}
+
+static void hpet_set_timer(HPETTimer *s)
+{
+ qemu_mod_timer(s->qemu_timer, qemu_get_clock(vm_clock)
+ + ticks_to_ns(s->period));
+}
+
+static void hpet_del_timer(HPETTimer *t)
+{
+ qemu_del_timer(t->qemu_timer);
+}
+static uint32_t hpet_ram_readb(void *opaque, target_phys_addr_t addr)
+{
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: hpet_read b at %" PRIx64 "\n", addr);
+#endif
+ return 10;
+}
+
+static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
+{
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: hpet_read w at %" PRIx64 "\n", addr);
+#endif
+ return 10;
+}
+
+static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
+{
+ HPETState *s = (HPETState *)opaque;
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: hpet_read l at %" PRIx64 "\n", addr);
+#endif
+ switch(addr - HPET_BASE) {
+ case HPET_ID:
+ return s->capability;
+ case HPET_PERIOD:
+ return s->capability >> 32;
+ case HPET_CFG:
+ return s->config;
+ case HPET_CFG + 4:
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: invalid hpet_read l at %" PRIx64 "\n", addr);
+#endif
+ return 0;
+ case HPET_COUNTER:
+ s->hpet_counter = ns_to_ticks(qemu_get_clock(vm_clock)
+ - s->hpet_offset) ;
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: reading counter %" PRIx64 "\n", s->hpet_counter);
+#endif
+ return s->hpet_counter;
+ case HPET_COUNTER + 4:
+ return 0;
+ case HPET_STATUS:
+ return s->isr;
+ case HPET_TN_REGS:
+ {
+ uint8_t timer_id = (addr - HPET_BASE - 0x100) / 0x20;
+ if (timer_id > HPET_NUM_TIMERS - 1) {
+ fprintf(stderr, "qemu: timer id out of range\n");
+ return 0;
+ }
+ HPETTimer *timer = &s->timer[timer_id];
+
+ switch((addr - HPET_BASE - 0x100) % 0x20) {
+ case HPET_TN_CFG:
+ return timer->config;
+ case HPET_TN_CFG + 4: // Interrupt capabilities
+ return timer->config >> 32;
+ case HPET_TN_CMP: // comparator register
+ return timer->cmp;
+ case HPET_TN_CMP + 4:
+ return timer->cmp >> 32;
+ case HPET_TN_ROUTE:
+ return timer->fsb >> 32;
+ }
+ }
+ break;
+ }
+
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: invalid hpet_read l at %" PRIx64 "\n", addr);
+#endif
+ return 10;
+}
+
+static void hpet_ram_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: invalid hpet_write b at %" PRIx64 " = %#x\n", addr, value);
+#endif
+}
+
+static void hpet_ram_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: invalid hpet_write w at %" PRIx64 " = %#x\n", addr, value);
+#endif
+}
+
+static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ int i;
+ HPETState *s = (HPETState *)opaque;
+ uint64_t old_val, new_val;
+
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: hpet_write l at %" PRIx64 " = %#x\n", addr, value);
+#endif
+ old_val = hpet_ram_readl(opaque, addr);
+ new_val = value;
+
+
+ switch(addr - HPET_BASE) {
+ case HPET_ID:
+ return;
+ case HPET_CFG:
+ s->config = hpet_fixup_reg(new_val, old_val, 0x3);
+ if (!(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE)) {
+ /* Enable main counter and interrupt generation. */
+ s->hpet_offset = qemu_get_clock(vm_clock)
+ - ticks_to_ns(s->hpet_counter);
+ for (i = 0; i < HPET_NUM_TIMERS; i++)
+ hpet_set_timer(&s->timer[i]);
+ }
+ else if ( (old_val & HPET_CFG_ENABLE) &&
+ !(new_val & HPET_CFG_ENABLE)) {
+ /* Halt main counter and disable interrupt generation. */
+ s->hpet_counter = ns_to_ticks(qemu_get_clock(vm_clock)
+ - s->hpet_offset) ;
+ for (i = 0; i < HPET_NUM_TIMERS; i++)
+ hpet_del_timer(&s->timer[i]);
+ }
+ hpet_legacy = s->config & HPET_CFG_LEGACY;
+ break;
+ case HPET_CFG + 4:
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: invalid hpet_write l at %" PRIx64 " = %#x\n", addr,
+ value);
+#endif
+ break;
+ case HPET_STATUS:
+ /* FIXME: need to handle level-triggered interrupts */
+ break;
+ case HPET_COUNTER:
+
+ if ((s->config & HPET_CFG_ENABLE))
+ fprintf(stderr, "qemu: Writing counter while HPET enabled!\n");
+ s->hpet_counter = value;
+ break;
+ case HPET_COUNTER + 4:
+ s->hpet_counter = (s->hpet_counter & 0xffffffffULL)
+ | (((uint64_t)value) << 32);
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: HPET counter 0xf4 set to %#x -> %" PRIx64 "\n",
+ value, s->hpet_counter);
+#endif
+ break;
+ case HPET_TN_REGS:
+ {
+ uint8_t timer_id = (addr - HPET_BASE - 0x100) / 0x20;
+#ifdef HPET_DEBUG
+ fprintf(stderr,
+ "qemu: hpet_write l timer_id = %#x \n",
+ timer_id);
+#endif
+ HPETTimer *timer = &s->timer[timer_id];
+
+ switch((addr - HPET_BASE - 0x100) % 0x20) {
+ case HPET_TN_CFG:
+#ifdef HPET_DEBUG
+ fprintf(stderr,
+ "qemu: hpet_write l comparator value %#x\n",
+ value);
+#endif
+ timer->config =
+ hpet_fixup_reg(new_val, old_val, 0x3f4e);
+#ifdef HPET_DEBUG
+ fprintf(stderr, "qemu: hpet_write l at %" PRIx64 " = %#x\n",
+ addr, value);
+#endif
+ if ( new_val & HPET_TN_32BIT ) {
+ timer->cmp = (uint32_t)timer->cmp;
+ timer->period = (uint32_t)timer->period;
+ }
+
+ break;
+#ifdef HPET_DEBUG
+ case HPET_TN_CFG + 4: // Interrupt capabilities
+ fprintf(stderr,
+ "qemu: invalid hpet_write l at %" PRIx64 " = %#x\n",
+ addr, value);
+ break;
+#endif
+ case HPET_TN_CMP: // comparator register
+#ifdef HPET_DEBUG
+ fprintf(stderr,
+ "qemu: hpet_write l comparator value %#x\n",
+ value);
+#endif
+ if ( timer->config & HPET_TN_32BIT)
+ new_val = (uint32_t)new_val;
+ if ( !timer_is_periodic(timer) ||
+ (timer->config & HPET_TN_SETVAL) )
+ timer->cmp = new_val;
+ else {
+ /*
+ * FIXME: Clamp period to reasonable min/max values:
+ */
+ timer->period = new_val;
+ }
+ timer->config &= ~HPET_TN_SETVAL;
+ if ( hpet_enabled(s) )
+ hpet_set_timer(timer);
+ break;
+
+ case HPET_TN_ROUTE + 4:
+#ifdef HPET_DEBUG
+ fprintf(stderr,
+ "qemu: invalid hpet_write l at %" PRIx64 " = %#x\n",
+ addr, value);
+#endif
+ break;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "qemu: invalid hpet_write l at %" PRIx64 " = %#x\n",
+ addr, value);
+ }
+
+}
+
+static CPUReadMemoryFunc *hpet_ram_read[] = {
+ hpet_ram_readb,
+ hpet_ram_readw,
+ hpet_ram_readl,
+};
+
+static CPUWriteMemoryFunc *hpet_ram_write[] = {
+ hpet_ram_writeb,
+ hpet_ram_writew,
+ hpet_ram_writel,
+};
+
+
+void hpet_init(qemu_irq *irq) {
+ int iomemtype, i;
+ HPETState *s;
+
+ /* XXX this is a dirty hack for HPET support w/o LPC
+ Actually this is a config descriptor for the RCBA */
+ fprintf (stderr, "hpet_init\n");
+ s = qemu_mallocz(sizeof(HPETState));
+ s->irqs = irq;
+ /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
+ s->capability = 0x8086A201ULL;
+ s->capability |= ((HPET_CLK_PERIOD) << 32);
+
+ for(i=0; i<HPET_NUM_TIMERS; i++) {
+ HPETTimer *timer = &s->timer[i];
+ timer->tn = i;
+ timer->cmp = ~0ULL;
+ timer->config = HPET_TN_PERIODIC_CAP;
+ timer->config |= 0x00ffULL << 32;
+ timer->state = s;
+ timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
+ }
+
+ /* HPET Area */
+
+ iomemtype = cpu_register_io_memory(0, hpet_ram_read,
+ hpet_ram_write, s);
+
+ cpu_register_physical_memory(HPET_BASE, 0x400, iomemtype);
+}
diff --git a/hw/i8254.c b/hw/i8254.c
index 4813b03..7ffdf61 100644
--- a/hw/i8254.c
+++ b/hw/i8254.c
@@ -26,6 +26,9 @@
#include "isa.h"
#include "qemu-timer.h"
+#if defined TARGET_I386 || defined TARGET_X86_64
+extern int hpet_legacy;
+#endif
//#define DEBUG_PIT
#define RW_STATE_LSB 1
@@ -367,6 +370,14 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
if (!s->irq_timer)
return;
+
+#if defined TARGET_I386 || defined TARGET_X86_64
+ if (hpet_legacy) {
+ qemu_del_timer(s->irq_timer);
+ return;
+ }
+#endif
+
expire_time = pit_get_next_transition_time(s, current_time);
irq_level = pit_get_out1(s, current_time);
qemu_set_irq(s->irq, irq_level);
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 30bb044..ffb7a48 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -27,6 +27,10 @@
#include "pc.h"
#include "isa.h"
+#if defined TARGET_I386 || defined TARGET_X86_64
+extern int hpet_legacy;
+#endif
+
//#define DEBUG_CMOS
#define RTC_SECONDS 0
@@ -80,7 +84,11 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
if (period_code != 0 &&
+#if defined TARGET_I386 || defined TARGET_X86_64
+ (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_legacy) {
+#else
(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+#endif
if (period_code <= 2)
period_code += 7;
/* period in 32 Khz cycles */
@@ -101,7 +109,10 @@ static void rtc_periodic_timer(void *opaque)
rtc_timer_update(s, s->next_periodic_time);
s->cmos_data[RTC_REG_C] |= 0xc0;
- qemu_irq_raise(s->irq);
+#if defined TARGET_I386 || defined TARGET_X86_64
+ if (!hpet_legacy)
+#endif
+ qemu_irq_raise(s->irq);
}
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
@@ -281,6 +292,12 @@ static void rtc_update_second(void *opaque)
RTCState *s = opaque;
int64_t delay;
+#if defined TARGET_I386 || defined TARGET_X86_64
+ if (hpet_legacy) {
+ qemu_del_timer(s->second_timer2);
+ return;
+ }
+#endif
/* if the oscillator is not in normal operation, we do not update */
if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
s->next_second_time += ticks_per_sec;
@@ -306,6 +323,12 @@ static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
+#if defined TARGET_I386 || defined TARGET_X86_64
+ if (hpet_legacy) {
+ qemu_del_timer(s->second_timer);
+ return;
+ }
+#endif
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_copy_date(s);
}
@@ -359,7 +382,10 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
break;
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
- qemu_irq_lower(s->irq);
+#if defined TARGET_I386 || defined TARGET_X86_64
+ if (!hpet_legacy)
+#endif
+ qemu_irq_lower(s->irq);
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:
diff --git a/hw/pc.c b/hw/pc.c
index fb3e0c9..80d5a19 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -46,6 +46,7 @@
#define ACPI_DATA_SIZE 0x10000
#define MAX_IDE_BUS 2
+void hpet_init(qemu_irq irq);
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
@@ -925,6 +926,7 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
}
pit = pit_init(0x40, i8259[0]);
pcspk_init(pit);
+ hpet_init(i8259);
if (pci_enabled) {
pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
2008-08-02 11:05 [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2) Beth Kon
@ 2008-08-02 11:38 ` Samuel Thibault
2008-08-02 14:46 ` Anthony Liguori
2008-08-02 11:42 ` Paul Brook
1 sibling, 1 reply; 7+ messages in thread
From: Samuel Thibault @ 2008-08-02 11:38 UTC (permalink / raw)
To: qemu-devel; +Cc: Beth Kon, Alexander Graf, kvm
Beth Kon, le Sat 02 Aug 2008 06:05:14 -0500, a écrit :
> I was trying to reproduce the wakeup every 10ms that
> Samuel Thibault mentioned, thinking the HPET would improve it.
> But for an idle guest in both cases (with and without HPET), the
> number of wakeups per second was relatively low (28).
I was referring to vl.c's timeout = 10; which makes the select call
use a timeout of 10ms. That said, "/* If all cpus are halted then wait
until the next IRQ */", so maybe that's why you get slower wakeups per
second. I'm still surprised because of the call to qemu_mod_timer in
pit_irq_timer_update which should setup at least a 100Hz timer with
linux guests (when they don't have HPET available).
Samuel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
2008-08-02 11:38 ` Samuel Thibault
@ 2008-08-02 14:46 ` Anthony Liguori
2008-08-02 17:21 ` Samuel Thibault
0 siblings, 1 reply; 7+ messages in thread
From: Anthony Liguori @ 2008-08-02 14:46 UTC (permalink / raw)
To: Samuel Thibault, qemu-devel, Beth Kon, Alexander Graf, kvm
Samuel Thibault wrote:
> Beth Kon, le Sat 02 Aug 2008 06:05:14 -0500, a écrit :
>
>> I was trying to reproduce the wakeup every 10ms that
>> Samuel Thibault mentioned, thinking the HPET would improve it.
>> But for an idle guest in both cases (with and without HPET), the
>> number of wakeups per second was relatively low (28).
>>
>
> I was referring to vl.c's timeout = 10; which makes the select call
> use a timeout of 10ms. That said, "/* If all cpus are halted then wait
> until the next IRQ */", so maybe that's why you get slower wakeups per
> second. I'm still surprised because of the call to qemu_mod_timer in
> pit_irq_timer_update which should setup at least a 100Hz timer with
> linux guests (when they don't have HPET available).
>
The patch disables that when hpet is active.
Regards,
Anthony Liguori
> Samuel
>
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
2008-08-02 14:46 ` Anthony Liguori
@ 2008-08-02 17:21 ` Samuel Thibault
2008-08-02 17:26 ` Samuel Thibault
2008-08-12 16:33 ` Beth Kon
0 siblings, 2 replies; 7+ messages in thread
From: Samuel Thibault @ 2008-08-02 17:21 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Beth Kon, qemu-devel, kvm, Alexander Graf
Anthony Liguori, le Sat 02 Aug 2008 09:46:30 -0500, a écrit :
> Samuel Thibault wrote:
> >Beth Kon, le Sat 02 Aug 2008 06:05:14 -0500, a écrit :
> >
> >>I was trying to reproduce the wakeup every 10ms that
> >>Samuel Thibault mentioned, thinking the HPET would improve it.
> >>But for an idle guest in both cases (with and without HPET), the
> >>number of wakeups per second was relatively low (28).
> >>
> >
> >I was referring to vl.c's timeout = 10; which makes the select call
> >use a timeout of 10ms. That said, "/* If all cpus are halted then wait
> >until the next IRQ */", so maybe that's why you get slower wakeups per
> >second. I'm still surprised because of the call to qemu_mod_timer in
> >pit_irq_timer_update which should setup at least a 100Hz timer with
> >linux guests (when they don't have HPET available).
> >
>
> The patch disables that when hpet is active.
That's why I would expect, indeed, but he is reporting that _without_
HPET he gets low wakeups per second already.
Samuel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
2008-08-02 17:21 ` Samuel Thibault
@ 2008-08-02 17:26 ` Samuel Thibault
2008-08-12 16:33 ` Beth Kon
1 sibling, 0 replies; 7+ messages in thread
From: Samuel Thibault @ 2008-08-02 17:26 UTC (permalink / raw)
To: Anthony Liguori, qemu-devel, Beth Kon, Alexander Graf, kvm
Samuel Thibault, le Sat 02 Aug 2008 18:21:03 +0100, a écrit :
> Anthony Liguori, le Sat 02 Aug 2008 09:46:30 -0500, a écrit :
> > Samuel Thibault wrote:
> > >Beth Kon, le Sat 02 Aug 2008 06:05:14 -0500, a écrit :
> > >
> > >>I was trying to reproduce the wakeup every 10ms that
> > >>Samuel Thibault mentioned, thinking the HPET would improve it.
> > >>But for an idle guest in both cases (with and without HPET), the
> > >>number of wakeups per second was relatively low (28).
> > >>
> > >
> > >I was referring to vl.c's timeout = 10; which makes the select call
> > >use a timeout of 10ms. That said, "/* If all cpus are halted then wait
> > >until the next IRQ */", so maybe that's why you get slower wakeups per
> > >second. I'm still surprised because of the call to qemu_mod_timer in
> > >pit_irq_timer_update which should setup at least a 100Hz timer with
> > >linux guests (when they don't have HPET available).
> > >
> >
> > The patch disables that when hpet is active.
>
> That's why I would expect, indeed, but he is reporting that _without_
what*
> HPET he gets low wakeups per second already.
Samuel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
2008-08-02 17:21 ` Samuel Thibault
2008-08-02 17:26 ` Samuel Thibault
@ 2008-08-12 16:33 ` Beth Kon
1 sibling, 0 replies; 7+ messages in thread
From: Beth Kon @ 2008-08-12 16:33 UTC (permalink / raw)
To: Samuel Thibault; +Cc: qemu-devel, kvm
On Sat, 2008-08-02 at 18:21 +0100, Samuel Thibault wrote:
> Anthony Liguori, le Sat 02 Aug 2008 09:46:30 -0500, a écrit :
> > Samuel Thibault wrote:
> > >Beth Kon, le Sat 02 Aug 2008 06:05:14 -0500, a écrit :
> > >
> > >>I was trying to reproduce the wakeup every 10ms that
> > >>Samuel Thibault mentioned, thinking the HPET would improve it.
> > >>But for an idle guest in both cases (with and without HPET), the
> > >>number of wakeups per second was relatively low (28).
> > >>
> > >
> > >I was referring to vl.c's timeout = 10; which makes the select call
> > >use a timeout of 10ms. That said, "/* If all cpus are halted then wait
> > >until the next IRQ */", so maybe that's why you get slower wakeups per
> > >second. I'm still surprised because of the call to qemu_mod_timer in
> > >pit_irq_timer_update which should setup at least a 100Hz timer with
> > >linux guests (when they don't have HPET available).
> > >
> >
> > The patch disables that when hpet is active.
>
> That's why I would expect, indeed, but he is reporting that _without_
> HPET he gets low wakeups per second already.
>
> Samuel
Yes, 28 is incorrect. I was misinterpreting the output of powertop,
shown here:
Wakeups-from-idle per second : 27.7 interval: 10.0s
no ACPI power usage estimate available
Top causes for wakeups:
46.1% ( 63.9) qemu-system-x86 : schedule_timeout (process_timeout)
36.5% ( 50.6) qemu-system-x86 : sys_timer_settime (posix_timer_fn)
...
The "Wakeups-from-idle per second" reports 27.7, but the powertop source
code shows that this value is the total wakeups-per-second divided by
the number of online processors. So the proper number of
wakeups-per-second caused by the select is 63.9, which makes more
sense.
Looking at the main_loop code, there is no way to get a timeout of
greater than 10 without setting icount.
> --
> 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
--
Elizabeth Kon (Beth)
IBM Linux Technology Center
Open Hypervisor Team
email: eak@us.ibm.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2)
2008-08-02 11:05 [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2) Beth Kon
2008-08-02 11:38 ` Samuel Thibault
@ 2008-08-02 11:42 ` Paul Brook
1 sibling, 0 replies; 7+ messages in thread
From: Paul Brook @ 2008-08-02 11:42 UTC (permalink / raw)
To: qemu-devel; +Cc: Beth Kon, Alexander Graf, kvm
> I've been playing with CONFIG_NO_HZ and been surprised by the
> results. I was trying to reproduce the wakeup every 10ms that
> Samuel Thibault mentioned, thinking the HPET would improve it.
> But for an idle guest in both cases (with and without HPET), the
> number of wakeups per second was relatively low (28). Ultimately
> this depends on exactly what the guest is doing
Linux can use the existing acpi PM timer a NO_HZ clocksource.
Paul
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2008-08-12 16:34 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-02 11:05 [Qemu-devel] [RFC][PATCH] Add HPET emulation to qemu (v2) Beth Kon
2008-08-02 11:38 ` Samuel Thibault
2008-08-02 14:46 ` Anthony Liguori
2008-08-02 17:21 ` Samuel Thibault
2008-08-02 17:26 ` Samuel Thibault
2008-08-12 16:33 ` Beth Kon
2008-08-02 11:42 ` Paul Brook
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).