From: Liu Ping Fan <qemulist@gmail.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
Anthony Liguori <anthony@codemonkey.ws>,
Jan Kiszka <jan.kiszka@siemens.com>
Subject: [Qemu-devel] [PATCH 4/5] hpet: deliver irq by irqfd when in dedicated thread mode
Date: Thu, 12 Sep 2013 13:24:52 +0800 [thread overview]
Message-ID: <1378963493-559-5-git-send-email-pingfank@linux.vnet.ibm.com> (raw)
In-Reply-To: <1378963493-559-1-git-send-email-pingfank@linux.vnet.ibm.com>
Running hpet in iothread, there could be variable payload, which
will finally affect the accurate of timing. So we want to run
hpet on dedicated thread.
For hpet, almost of the things can run out of BQL, except interrupt.
We step around interrupt by using irqfd.
Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
hw/timer/hpet.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 50 insertions(+), 4 deletions(-)
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index ff43850..ae54b87 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -33,6 +33,7 @@
#include "hw/sysbus.h"
#include "hw/timer/mc146818rtc.h"
#include "hw/timer/i8254.h"
+#include "sysemu/kvm.h"
//#define HPET_DEBUG
#ifdef HPET_DEBUG
@@ -68,6 +69,12 @@ typedef struct HPETTimer { /* timers */
*/
} HPETTimer;
+typedef struct IrqfdInfo {
+ EventNotifier *n;
+ EventNotifier *rn;
+ int gsi;
+} IrqfdInfo;
+
typedef struct HPETState {
/*< private >*/
SysBusDevice parent_obj;
@@ -76,12 +83,14 @@ typedef struct HPETState {
MemoryRegion iomem;
uint64_t hpet_offset;
qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+ IrqfdInfo irqfds[HPET_NUM_IRQ_ROUTES];
uint32_t flags;
uint8_t rtc_irq_level;
qemu_irq pit_enabled;
uint8_t num_timers;
uint32_t intcap;
HPETTimer timer[HPET_MAX_TIMERS];
+ bool dedicate_mode;
/* Memory-mapped, software visible registers */
uint64_t capability; /* capabilities */
@@ -206,14 +215,19 @@ static void update_irq(struct HPETTimer *timer, int set)
if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
s->isr &= ~mask;
if (!timer_fsb_route(timer)) {
- /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
- if (route >= ISA_NUM_IRQS) {
- qemu_irq_raise(s->irqs[route]);
+ if (s->dedicate_mode && s->irqfds[timer->tn].n) {
+ event_notifier_set(s->irqfds[timer->tn].n);
} else {
- qemu_irq_lower(s->irqs[route]);
+ /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
+ if (route >= ISA_NUM_IRQS) {
+ qemu_irq_raise(s->irqs[route]);
+ } else {
+ qemu_irq_lower(s->irqs[route]);
+ }
}
}
} else if (timer_fsb_route(timer)) {
+ /* For the case of fsb, we resort to the lock in mem dispatcher */
stl_le_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
} else if (timer->config & HPET_TN_TYPE_LEVEL) {
s->isr |= mask;
@@ -479,6 +493,32 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
return 0;
}
+static void timer_assign_irqfd(HPETState *s, HPETTimer *timer, bool assign)
+{
+ int irqnum = (timer->config & HPET_TN_INT_ROUTE_MASK)
+ >> HPET_TN_INT_ROUTE_SHIFT;
+ int level = timer->fsb & HPET_TN_TYPE_LEVEL;
+ IrqfdInfo *info = &s->irqfds[timer->tn];
+
+ if (assign) {
+ if (!info->n) {
+ info->n = g_new0(EventNotifier, 1);
+ info->rn = g_new0(EventNotifier, 1);
+ event_notifier_init(info->n, 0);
+ event_notifier_init(info->rn, 0);
+ }
+ info->gsi = qemu_irq_route_gsi(s->irqs[irqnum]);
+ kvm_irqchip_add_irqfd_notifier(kvm_state, info->n,
+ level ? info->rn : NULL, info->gsi, 1);
+ } else {
+ kvm_irqchip_remove_irqfd_notifier(kvm_state, info->n, info->gsi);
+ g_free(info->n);
+ g_free(info->rn);
+ info->n = NULL;
+ info->rn = NULL;
+ }
+}
+
static void hpet_ram_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
@@ -514,8 +554,14 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
timer->period = (uint32_t)timer->period;
}
if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+ if (s->dedicate_mode) {
+ timer_assign_irqfd(s, timer, true);
+ }
hpet_set_timer(timer);
} else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+ if (s->dedicate_mode) {
+ timer_assign_irqfd(s, timer, false);
+ }
hpet_del_timer(timer);
}
break;
--
1.8.1.4
next prev parent reply other threads:[~2013-09-12 5:26 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-12 5:24 [Qemu-devel] [RFC 0/5] run hpet on a dedicated thread Liu Ping Fan
2013-09-12 5:24 ` [Qemu-devel] [PATCH 1/5] irq: introduce route method in IRQState to get gsi Liu Ping Fan
2013-09-12 5:24 ` [Qemu-devel] [PATCH 2/5] irq: implement route method of ioapic Liu Ping Fan
2013-09-12 5:24 ` [Qemu-devel] [PATCH 3/5] irqfd: equip irqfd with polarity Liu Ping Fan
2013-09-12 5:24 ` Liu Ping Fan [this message]
2013-09-12 5:24 ` [Qemu-devel] [PATCH 5/5] hpet: run on dedicate thread Liu Ping Fan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1378963493-559-5-git-send-email-pingfank@linux.vnet.ibm.com \
--to=qemulist@gmail.com \
--cc=anthony@codemonkey.ws \
--cc=jan.kiszka@siemens.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).