========
PM: mapping to 0xb000
PM readw port=0x0004 val=0x0000
...
gpe write afe2 <== 0
gpe write afe0 <== 255
gpe write afe3 <== 0
gpe write afe1 <== 255
PM readw port=0x0000 val=0x0001
PM readw port=0x0002 val=0x0000
gpe read afe0 == 0
gpe read afe2 == 0
gpe read afe1 == 0
gpe read afe3 == 0
PM writew port=0x0000 val=0x0020
PM readw port=0x0002 val=0x0000
PM writew port=0x0002 val=0x0020
PM readw port=0x0002 val=0x0020
gpe write afe2 <== 255
gpe write afe3 <== 255
...
slot: 6, up: 0, down: 0, state: 1   <==== we attach interface the first time
PM readw port=0x0000 val=0x0001
PM readw port=0x0002 val=0x0120
gpe read afe0 == 2
gpe read afe2 == ff
gpe read afe2 == ff
gpe write afe2 <== 253
gpe read afe1 == 0
gpe read afe3 == ff
pcihotplug read ae00 == 40
pcihotplug read ae04 == 0
...
gpe write afe0 <== 2
gpe write afe2 <== 255
slot: 6, up: 64, down: 0, state: 0  <===== we detach interface the first time
PM readw port=0x0000 val=0x0001
PM readw port=0x0002 val=0x0120
gpe read afe0 == 2
gpe read afe2 == ff
gpe read afe2 == ff
gpe write afe2 <== 253
gpe read afe1 == 0
gpe read afe3 == ff
pcihotplug read ae00 == 0
pcihotplug read ae04 == 40
...
pciej write ae08 <== 64		<=== we will call qdev_free()
pciej write ae08 <== 64
gpe write afe0 <== 2
gpe write afe2 <== 255
slot: 7, up: 0, down: 64, state: 1  <=== we attach interface the second time.
PM readw port=0x0000 val=0x0001
PM readw port=0x0002 val=0x0120
gpe read afe0 == 2
gpe read afe2 == ff
gpe read afe2 == ff
gpe write afe2 <== 253
gpe read afe1 == 0
gpe read afe3 == ff
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
pcihotplug read ae00 == 80
pcihotplug read ae04 == 0
slot: 7, up: 128, down: 0, state: 0  <=== we detach interface the second time
gpe write afe0 <== 2		<=== write 2 to afe0 will cause sci interupt to be lost
gpe write afe2 <== 255
===========

Here is short log, and show the different between the first time and second time:
===========
gpe write afe0 <== 2
gpe write afe2 <== 255
slot: 6, up: 64, down: 0, state: 0  <===== we detach interface the first time
....
slot: 7, up: 128, down: 0, state: 0  <=== we detach interface the second time
gpe write afe0 <== 2		<=== write 2 to afe0 will cause sci interupt to be lost
gpe write afe2 <== 255

===========

Does this behavior is a normal behavior?

The following patch can fix this problem.

From 3c149575b52261b8da9a73d5c4ebdfedce9866c1 Mon Sep 17 00:00:00 2001
From: Wen Congyang <wency@cn.fujitsu.com>
Date: Mon, 28 Feb 2011 10:33:45 +0800
Subject: [PATCH] pend hotplug event until last event is handled by guest OS

---
 hw/acpi_piix4.c |   51 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index b5a2762..4ff3475 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -74,6 +74,7 @@ typedef struct PIIX4PMState {
     /* for pci hotplug */
     struct gpe_regs gpe;
     struct pci_status pci0_status;
+    struct pci_status pci0_status_pending;
     uint32_t pci0_hotplug_enable;
 } PIIX4PMState;
 
@@ -518,6 +519,19 @@ static void gpe_reset_val(uint16_t *cur, int addr, uint32_t val)
     *cur = (*cur & (0xff << (8 - shift))) | (x1 << shift);
 }
 
+static void raise_pending_hotplug(PIIX4PMState *s)
+{
+    if (s->pci0_status_pending.up || s->pci0_status_pending.down) {
+        s->gpe.sts |= PIIX4_PCI_HOTPLUG_STATUS;
+        s->pci0_status.up = s->pci0_status_pending.up;
+        s->pci0_status.down = s->pci0_status_pending.down;
+        s->pci0_status_pending.up = 0;
+        s->pci0_status_pending.down = 0;
+
+        pm_update_sci(s);
+    }
+}
+
 static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
 {
     PIIX4PMState *s = opaque;
@@ -539,6 +553,11 @@ static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
     pm_update_sci(s);
 
     PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val);
+
+    if (!(g->sts & PIIX4_PCI_HOTPLUG_STATUS) && g->en & PIIX4_PCI_HOTPLUG_STATUS) {
+        /* check and reraise the pending hotplug event */
+        raise_pending_hotplug(s);
+    }
 }
 
 static uint32_t pcihotplug_read(void *opaque, uint32_t addr)
@@ -639,12 +658,22 @@ static void enable_device(PIIX4PMState *s, int slot)
     s->pci0_status.up |= (1 << slot);
 }
 
+static void pend_enable_device(PIIX4PMState *s, int slot)
+{
+    s->pci0_status_pending.up |= (1 << slot);
+}
+
 static void disable_device(PIIX4PMState *s, int slot)
 {
     s->gpe.sts |= PIIX4_PCI_HOTPLUG_STATUS;
     s->pci0_status.down |= (1 << slot);
 }
 
+static void pend_disable_device(PIIX4PMState *s, int slot)
+{
+    s->pci0_status_pending.down |= (1 << slot);
+}
+
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 				PCIHotplugState state)
 {
@@ -659,15 +688,23 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
         return 0;
     }
 
-    s->pci0_status.up = 0;
-    s->pci0_status.down = 0;
-    if (state == PCI_HOTPLUG_ENABLED) {
-        enable_device(s, slot);
+    if (s->gpe.sts & PIIX4_PCI_HOTPLUG_STATUS) {
+        if (state == PCI_HOTPLUG_ENABLED) {
+            pend_enable_device(s, slot);
+        } else {
+            pend_disable_device(s, slot);
+        }
     } else {
-        disable_device(s, slot);
-    }
+        s->pci0_status.up = 0;
+        s->pci0_status.down = 0;
+        if (state == PCI_HOTPLUG_ENABLED) {
+            enable_device(s, slot);
+        } else {
+            disable_device(s, slot);
+        }
 
-    pm_update_sci(s);
+        pm_update_sci(s);
+    }
 
     return 0;
 }
