From patchwork Mon Feb 12 08:57:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gonglei (Arei)" X-Patchwork-Id: 10212001 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 79A4E60467 for ; Mon, 12 Feb 2018 08:59:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6DA1528A25 for ; Mon, 12 Feb 2018 08:59:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 61DB328BBB; Mon, 12 Feb 2018 08:59:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 448AC28A25 for ; Mon, 12 Feb 2018 08:59:16 +0000 (UTC) Received: from localhost ([::1]:57378 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1el9xD-0002OY-Sh for patchwork-qemu-devel@patchwork.kernel.org; Mon, 12 Feb 2018 03:59:15 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60046) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1el9wP-0001nJ-VJ for qemu-devel@nongnu.org; Mon, 12 Feb 2018 03:58:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1el9wL-0002jm-NA for qemu-devel@nongnu.org; Mon, 12 Feb 2018 03:58:26 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:2166 helo=huawei.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1el9wL-0002fi-3g for qemu-devel@nongnu.org; Mon, 12 Feb 2018 03:58:21 -0500 Received: from DGGEMS409-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id E31822414B9BA; Mon, 12 Feb 2018 16:58:03 +0800 (CST) Received: from localhost (10.177.18.62) by DGGEMS409-HUB.china.huawei.com (10.3.19.209) with Microsoft SMTP Server id 14.3.361.1; Mon, 12 Feb 2018 16:57:54 +0800 From: Gonglei To: Date: Mon, 12 Feb 2018 16:57:51 +0800 Message-ID: <1518425871-145512-1-git-send-email-arei.gonglei@huawei.com> X-Mailer: git-send-email 2.8.2.windows.1 MIME-Version: 1.0 X-Originating-IP: [10.177.18.62] X-CFilter-Loop: Reflected X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 45.249.212.190 Subject: [Qemu-devel] [PATCH v3] rtc: placing RTC memory region outside BQL X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, Gonglei , weidong.huang@huawei.com, peter.maydell@linaro.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP As windows guest use rtc as the clock source device, and access rtc frequently. Let's move the rtc memory region outside BQL to decrease overhead for windows guests. Meanwhile, adding a new lock to avoid different vCPUs access the RTC together. I tested PCMark 8 (https://www.futuremark.com/benchmarks/pcmark) in win7 guest and got the below results: Guest: 2U2G Before applying the patch: Your Work 2.0 score: 2000 Web Browsing - JunglePin 0.334s Web Browsing - Amazonia 0.132s Writing 3.59s Spreadsheet 70.13s Video Chat v2/Video Chat playback 1 v2 22.8 fps Video Chat v2/Video Chat encoding v2 307.0 ms Benchmark duration 1h 35min 46s After applying the patch: Your Work 2.0 score: 2040 Web Browsing - JunglePin 0.345s Web Browsing - Amazonia 0.132s Writing 3.56s Spreadsheet 67.83s Video Chat v2/Video Chat playback 1 v2 28.7 fps Video Chat v2/Video Chat encoding v2 324.7 ms Benchmark duration 1h 32min 5s Test results show that optimization is effective under stressful situations. Signed-off-by: Gonglei --- v3->v2: a) fix a typo, 's/rasie/raise/' [Peter] b) change commit message [Peter] v2->v1: a)Adding a new lock to avoid different vCPUs access the RTC together. [Paolo] b)Taking the BQL before raising the outbound IRQ line. [Peter] c)Don't hold BQL if it was holden. [Peter] hw/timer/mc146818rtc.c | 55 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 35a05a6..f0a2a62 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -85,6 +85,7 @@ typedef struct RTCState { uint16_t irq_reinject_on_ack_count; uint32_t irq_coalesced; uint32_t period; + QemuMutex rtc_lock; QEMUTimer *coalesced_timer; Notifier clock_reset_notifier; LostTickPolicy lost_tick_policy; @@ -125,6 +126,36 @@ static void rtc_coalesced_timer_update(RTCState *s) } } +static void rtc_raise_irq(RTCState *s) +{ + bool unlocked = !qemu_mutex_iothread_locked(); + + if (unlocked) { + qemu_mutex_lock_iothread(); + } + + qemu_irq_raise(s->irq); + + if (unlocked) { + qemu_mutex_unlock_iothread(); + } +} + +static void rtc_lower_irq(RTCState *s) +{ + bool unlocked = !qemu_mutex_iothread_locked(); + + if (unlocked) { + qemu_mutex_lock_iothread(); + } + + qemu_irq_lower(s->irq); + + if (unlocked) { + qemu_mutex_unlock_iothread(); + } +} + static QLIST_HEAD(, RTCState) rtc_devices = QLIST_HEAD_INITIALIZER(rtc_devices); @@ -141,7 +172,7 @@ void qmp_rtc_reset_reinjection(Error **errp) static bool rtc_policy_slew_deliver_irq(RTCState *s) { apic_reset_irq_delivered(); - qemu_irq_raise(s->irq); + rtc_raise_irq(s); return apic_get_irq_delivered(); } @@ -277,8 +308,9 @@ static void rtc_periodic_timer(void *opaque) DPRINTF_C("cmos: coalesced irqs increased to %d\n", s->irq_coalesced); } - } else - qemu_irq_raise(s->irq); + } else { + rtc_raise_irq(s); + } } } @@ -459,7 +491,7 @@ static void rtc_update_timer(void *opaque) s->cmos_data[RTC_REG_C] |= irqs; if ((new_irqs & s->cmos_data[RTC_REG_B]) != 0) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; - qemu_irq_raise(s->irq); + rtc_raise_irq(s); } check_update_timer(s); } @@ -471,6 +503,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, uint32_t old_period; bool update_periodic_timer; + qemu_mutex_lock(&s->rtc_lock); if ((addr & 1) == 0) { s->cmos_index = data & 0x7f; } else { @@ -560,10 +593,10 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, * becomes enabled, raise an interrupt immediately. */ if (data & s->cmos_data[RTC_REG_C] & REG_C_MASK) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; - qemu_irq_raise(s->irq); + rtc_raise_irq(s); } else { s->cmos_data[RTC_REG_C] &= ~REG_C_IRQF; - qemu_irq_lower(s->irq); + rtc_lower_irq(s); } s->cmos_data[RTC_REG_B] = data; @@ -583,6 +616,7 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, break; } } + qemu_mutex_unlock(&s->rtc_lock); } static inline int rtc_to_bcd(RTCState *s, int a) @@ -710,6 +744,7 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, if ((addr & 1) == 0) { return 0xff; } else { + qemu_mutex_lock(&s->rtc_lock); switch(s->cmos_index) { case RTC_IBM_PS2_CENTURY_BYTE: s->cmos_index = RTC_CENTURY; @@ -737,7 +772,7 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, break; case RTC_REG_C: ret = s->cmos_data[s->cmos_index]; - qemu_irq_lower(s->irq); + rtc_lower_irq(s); s->cmos_data[RTC_REG_C] = 0x00; if (ret & (REG_C_UF | REG_C_AF)) { check_update_timer(s); @@ -762,6 +797,7 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, } CMOS_DPRINTF("cmos: read index=0x%02x val=0x%02x\n", s->cmos_index, ret); + qemu_mutex_unlock(&s->rtc_lock); return ret; } } @@ -909,7 +945,7 @@ static void rtc_reset(void *opaque) s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF); check_update_timer(s); - qemu_irq_lower(s->irq); + rtc_lower_irq(s); if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { s->irq_coalesced = 0; @@ -960,6 +996,8 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) rtc_set_date_from_host(isadev); + qemu_mutex_init(&s->rtc_lock); + switch (s->lost_tick_policy) { #ifdef TARGET_I386 case LOST_TICK_POLICY_SLEW: @@ -986,6 +1024,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) qemu_register_suspend_notifier(&s->suspend_notifier); memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2); + memory_region_clear_global_locking(&s->io); isa_register_ioport(isadev, &s->io, base); qdev_set_legacy_instance_id(dev, base, 3);