[PATCH] [HVM] Fixed 2 bugs for smp HVM PV driver save/restore
1. After restore, if AP's HYPERVISOR_yield() happen when BSP reinitialize
hyper-call
page in resume_hypercall_stubs(), there is a crash. Add a rwlock to fix it.
2. For pseudo PCI dev if an intr is asserted but not deasserted and save happen,
after restore gsi_assert_count got increased so that vioapic_update_EOI will
continuously deliver intr W/O any chance to deasserted as
callback_via_asserted
is lost during save/restore. Force a deassert in such case to avoid deadlock.
Signed-off-by: Edwin Zhai <edwin.zhai@xxxxxxxxx>
diff -r 88bb0d305308 unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c
--- a/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Wed Aug
01 15:47:54 2007 +0100
+++ b/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Mon Aug
06 13:55:10 2007 +0800
@@ -10,6 +10,12 @@ struct ap_suspend_info {
int do_spin;
atomic_t nr_spinning;
};
+
+/*
+ * use a rwlock to protect the hypercall page in case that AP execute
+ * the hypercall code when BSP re-initialize it after restore
+ */
+DEFINE_RWLOCK(suspend_lock);
/*
* Spinning prevents, for example, APs touching grant table entries while
@@ -27,7 +33,9 @@ static void ap_suspend(void *_info)
while (info->do_spin) {
cpu_relax();
+ read_lock(&suspend_lock);
HYPERVISOR_yield();
+ read_unlock(&suspend_lock);
}
mb();
@@ -43,7 +51,9 @@ static int bp_suspend(void)
suspend_cancelled = HYPERVISOR_shutdown(SHUTDOWN_suspend);
if (!suspend_cancelled) {
+ write_lock(&suspend_lock);
platform_pci_resume();
+ write_unlock(&suspend_lock);
gnttab_resume();
irq_resume();
}
diff -r 88bb0d305308 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c Wed Aug 01 15:47:54 2007 +0100
+++ b/xen/arch/x86/hvm/irq.c Mon Aug 06 14:37:50 2007 +0800
@@ -395,6 +395,35 @@ static int irq_save_pci(struct domain *d
static int irq_save_pci(struct domain *d, hvm_domain_context_t *h)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ unsigned int gsi, pdev, pintx;
+
+ /*
+ * deassert if necessary to avoid PV drv deadlock in following case:
+ * gsi_assert_count got increased when assert then save happen,
+ * after restore gsi_assert_count got increased again so that
+ * vioapic_update_EOI will continue dilver intr W/O any chance
+ * to deassert as callback_via_asserted is 0.
+ */
+ if ( hvm_irq->callback_via_asserted ) {
+
+ switch ( hvm_irq->callback_via_type )
+ {
+ case HVMIRQ_callback_gsi:
+ gsi = hvm_irq->callback_via.gsi;
+ if ( (--hvm_irq->gsi_assert_count[gsi] == 0) && (gsi <= 15) )
+ vpic_irq_negative_edge(d, gsi);
+ gdprintk(XENLOG_INFO, "deassert gsi %d, cnt %d.\n", gsi,
hvm_irq->gsi_assert_count[gsi]);
+ break;
+ case HVMIRQ_callback_pci_intx:
+ pdev = hvm_irq->callback_via.pci.dev;
+ pintx = hvm_irq->callback_via.pci.intx;
+ __hvm_pci_intx_deassert(d, pdev, pintx);
+ gdprintk(XENLOG_INFO, "deassert pci pdev %d, pintx %d.\n",
pdev, pintx);
+ break;
+ default:
+ break;
+ }
+ }
/* Save PCI IRQ lines */
return ( hvm_save_entry(PCI_IRQ, 0, h, &hvm_irq->pci_intx) );
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|