From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:43058) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SF2II-0004v7-0T for qemu-devel@nongnu.org; Tue, 03 Apr 2012 07:53:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SF2IB-00051j-PA for qemu-devel@nongnu.org; Tue, 03 Apr 2012 07:53:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:25701) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SF2IB-00051c-Gy for qemu-devel@nongnu.org; Tue, 03 Apr 2012 07:52:55 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q33Bqrhr010884 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 3 Apr 2012 07:52:53 -0400 Received: from nial.brq.redhat.com (dhcp-1-247.brq.redhat.com [10.34.1.247]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q33BqqSG021598 for ; Tue, 3 Apr 2012 07:52:53 -0400 From: Igor Mammedov Date: Tue, 3 Apr 2012 13:52:52 +0200 Message-Id: <1333453972-24695-1-git-send-email-imammedo@redhat.com> Subject: [Qemu-devel] [PATCH] Fix race resulting in loosing event bit in GPE.1.sts List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org After receiving hotplug gpe event, guest masks event in GPE.1.en register, executes associated AML handler and then resets event bit in GPE.1.sts. If another pci device was hot-plugged after AML handler has been executed and before event bit is reset in GPE.1.sts, then guest will loose GPE event and it will not see all hotplugged devices. Could be reproduced with: ./QMP/qmp device_add --driver=e1000 && sleep 0.X && ./QMP/qmp device_add --driver=e1000 Signed-off-by: Igor Mammedov --- hw/acpi.c | 23 ++++++++++++++++++++++- hw/acpi.h | 1 + hw/acpi_piix4.c | 7 +++++++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/hw/acpi.c b/hw/acpi.c index 5d521e5..be6efab 100644 --- a/hw/acpi.c +++ b/hw/acpi.c @@ -412,6 +412,7 @@ void acpi_gpe_init(ACPIREGS *ar, uint8_t len) ar->gpe.len = len; ar->gpe.sts = g_malloc0(len / 2); ar->gpe.en = g_malloc0(len / 2); + ar->gpe.pending_sts = g_malloc0(len / 2); } void acpi_gpe_blk(ACPIREGS *ar, uint32_t blk) @@ -423,6 +424,7 @@ void acpi_gpe_reset(ACPIREGS *ar) { memset(ar->gpe.sts, 0, ar->gpe.len / 2); memset(ar->gpe.en, 0, ar->gpe.len / 2); + memset(ar->gpe.pending_sts, 0, ar->gpe.len / 2); } static uint8_t *acpi_gpe_ioport_get_ptr(ACPIREGS *ar, uint32_t addr) @@ -440,15 +442,34 @@ static uint8_t *acpi_gpe_ioport_get_ptr(ACPIREGS *ar, uint32_t addr) return cur; } +static uint8_t *acpi_gpe_get_pend_sts_ptr(ACPIREGS *ar, uint32_t addr) +{ + uint8_t *cur = NULL; + + if (addr < ar->gpe.len / 2) { + cur = ar->gpe.pending_sts + addr; + } else { + abort(); + } + + return cur; + +} + void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val) { - uint8_t *cur; + uint8_t *cur, *psts; addr -= ar->gpe.blk; cur = acpi_gpe_ioport_get_ptr(ar, addr); if (addr < ar->gpe.len / 2) { /* GPE_STS */ *cur = (*cur) & ~val; + psts = acpi_gpe_get_pend_sts_ptr(ar, addr); + if (*cur != *psts) { + *cur |= *psts; + *psts = 0; + } } else if (addr < ar->gpe.len) { /* GPE_EN */ *cur = val; diff --git a/hw/acpi.h b/hw/acpi.h index fe8cdb4..6a6953d 100644 --- a/hw/acpi.h +++ b/hw/acpi.h @@ -104,6 +104,7 @@ struct ACPIGPE { uint8_t *sts; uint8_t *en; + uint8_t *pending_sts; }; struct ACPIREGS { diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 797ed24..ce50d85 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -66,6 +66,9 @@ typedef struct PIIX4PMState { int kvm_enabled; Notifier machine_ready; + /* for hotplug */ + uint16_t pending_gpe_events; + /* for pci hotplug */ struct pci_status pci0_status; uint32_t pci0_hotplug_enable; @@ -575,6 +578,10 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, disable_device(s, slot); } + if (~s->ar.gpe.en[0] & PIIX4_PCI_HOTPLUG_STATUS) { + s->ar.gpe.pending_sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; + } + pm_update_sci(s); return 0; -- 1.7.7.6