From patchwork Fri Dec 9 13:34:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Evgeny Voevodin X-Patchwork-Id: 130375 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BCFE01007D7 for ; Sat, 10 Dec 2011 00:35:34 +1100 (EST) Received: from localhost ([::1]:37371 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RZ0bq-0004XU-Bj for incoming@patchwork.ozlabs.org; Fri, 09 Dec 2011 08:35:30 -0500 Received: from eggs.gnu.org ([140.186.70.92]:34473) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RZ0bh-0004Lc-5T for qemu-devel@nongnu.org; Fri, 09 Dec 2011 08:35:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RZ0bf-0000Y3-GU for qemu-devel@nongnu.org; Fri, 09 Dec 2011 08:35:20 -0500 Received: from mailout3.w1.samsung.com ([210.118.77.13]:8508) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RZ0bf-0000Xq-3P for qemu-devel@nongnu.org; Fri, 09 Dec 2011 08:35:19 -0500 MIME-version: 1.0 Content-transfer-encoding: 7BIT Content-type: TEXT/PLAIN Received: from euspt2 ([210.118.77.13]) by mailout3.w1.samsung.com (Sun Java(tm) System Messaging Server 6.3-8.04 (built Jul 29 2009; 32bit)) with ESMTP id <0LVX005STV2T5S50@mailout3.w1.samsung.com> for qemu-devel@nongnu.org; Fri, 09 Dec 2011 13:35:17 +0000 (GMT) Received: from evvoevodinPC.rnd.samsung.ru ([106.109.8.48]) by spt2.w1.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTPA id <0LVX00MANV28B5@spt2.w1.samsung.com> for qemu-devel@nongnu.org; Fri, 09 Dec 2011 13:35:17 +0000 (GMT) Date: Fri, 09 Dec 2011 17:34:35 +0400 From: Evgeny Voevodin In-reply-to: <1323437682-28792-1-git-send-email-e.voevodin@samsung.com> To: qemu-devel@nongnu.org Message-id: <1323437682-28792-9-git-send-email-e.voevodin@samsung.com> X-Mailer: git-send-email 1.7.4.1 References: <1323437682-28792-1-git-send-email-e.voevodin@samsung.com> X-detected-operating-system: by eggs.gnu.org: Solaris 9.1 X-Received-From: 210.118.77.13 Cc: m.kozlov@samsung.com, d.solodkiy@samsung.com, Evgeny Voevodin Subject: [Qemu-devel] [PATCH 08/15] hw/arm_gic.c: lower IRQ only on changing of enable bit. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org In previous version IRQ was lowered every time if enable bits were not set. If platform has splitted IRQ source to pass IRQ to two identical GICs simultaneously in first of which IRQ passing is enabled but in second is disabled, handling IRQ by second GIC would lower IRQ previously raised by first GIC. Linux kernel v3.0 faces this problem. The problem is avoided if IRQ is only lowered as result of transitioning enable bits to zeroes. Signed-off-by: Evgeny Voevodin --- hw/arm_gic.c | 20 +++++++++++++++++++- 1 files changed, 19 insertions(+), 1 deletions(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index 527c9ce..7e3db4f 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -84,7 +84,9 @@ typedef struct gic_state SysBusDevice busdev; qemu_irq parent_irq[NCPU]; int enabled; + int enabled_prev; int cpu_enabled[NCPU]; + int cpu_enabled_prev[NCPU]; gic_irq_state irq_state[GIC_NIRQ]; #ifndef NVIC @@ -116,12 +118,22 @@ static void gic_update(gic_state *s) int level; int cpu; int cm; + int enabled_prev; + int cpu_enabled_prev; + enabled_prev = s->enabled_prev; + s->enabled_prev = s->enabled; for (cpu = 0; cpu < NUM_CPU(s); cpu++) { + cpu_enabled_prev = s->cpu_enabled_prev[cpu]; + s->cpu_enabled_prev[cpu] = s->cpu_enabled[cpu]; cm = 1 << cpu; s->current_pending[cpu] = 1023; if (!s->enabled || !s->cpu_enabled[cpu]) { - qemu_irq_lower(s->parent_irq[cpu]); + /* lower IRQ only if enable bit was changed */ + if (enabled_prev != s->enabled + || cpu_enabled_prev != s->cpu_enabled[cpu]) { + qemu_irq_lower(s->parent_irq[cpu]); + } return; } best_prio = 0x100; @@ -650,6 +662,7 @@ static void gic_reset(gic_state *s) #else s->cpu_enabled[i] = 0; #endif + s->cpu_enabled_prev[i] = s->cpu_enabled[i]; } for (i = 0; i < 16; i++) { GIC_SET_ENABLED(i, ALL_CPU_MASK); @@ -661,6 +674,7 @@ static void gic_reset(gic_state *s) #else s->enabled = 0; #endif + s->enabled_prev = s->enabled; } static void gic_save(QEMUFile *f, void *opaque) @@ -669,8 +683,10 @@ static void gic_save(QEMUFile *f, void *opaque) int i; int j; + qemu_put_be32(f, s->enabled_prev); qemu_put_be32(f, s->enabled); for (i = 0; i < NUM_CPU(s); i++) { + qemu_put_be32(f, s->cpu_enabled_prev[i]); qemu_put_be32(f, s->cpu_enabled[i]); for (j = 0; j < 32; j++) qemu_put_be32(f, s->priority1[j][i]); @@ -706,8 +722,10 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id) if (version_id != 2) return -EINVAL; + s->enabled_prev = qemu_get_be32(f); s->enabled = qemu_get_be32(f); for (i = 0; i < NUM_CPU(s); i++) { + s->cpu_enabled_prev[i] = qemu_get_be32(f); s->cpu_enabled[i] = qemu_get_be32(f); for (j = 0; j < 32; j++) s->priority1[j][i] = qemu_get_be32(f);