Module Name:    src
Committed By:   jym
Date:           Fri Jul 24 11:30:29 UTC 2009

Modified Files:
        src/sys/arch/x86/include [jym-xensuspend]: pmap.h
        src/sys/arch/x86/x86 [jym-xensuspend]: pmap.c
        src/sys/arch/xen/include [jym-xensuspend]: xenpmap.h
        src/sys/arch/xen/x86 [jym-xensuspend]: x86_xpmap.c
        src/sys/arch/xen/xen [jym-xensuspend]: xen_machdep.c xencons.c

Log Message:
- rework the page pinning API, so that now a function is provided for
each level of indirection encountered during virtual memory translations. Update
pmap accordingly. Pinning looks cleaner that way, and it offers the possibility
to pin lower level pages if necessary (NetBSD does not do it currently).

- some fixes and comments to explain how page validation/invalidation take
place during save/restore/migrate under Xen. L2 shadow entries from PAE are now
handled, so basically, suspend/resume works with PAE.

- fixes an issue reported by Christoph (cegger@) for xencons suspend/resume
in dom0.

TODO:

- PAE save/restore is currently limited to single-user only, multi-user
support requires modifications in PAE pmap that should be discussed first. See
the comments about the L2 shadow pages cached in pmap_pdp_cache in this commit.

- grant table bug is still there; do not use the kernels of this branch
to test suspend/resume, unless you want to experience bad crashes in dom0,
and push the big red button.

Now there is light at the end of the tunnel :)

Note: XEN2 kernels will neither build nor work with this branch.


To generate a diff of this commit:
cvs rdiff -u -r1.21.2.3 -r1.21.2.4 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.77.2.4 -r1.77.2.5 src/sys/arch/x86/x86/pmap.c
cvs rdiff -u -r1.21.8.2 -r1.21.8.3 src/sys/arch/xen/include/xenpmap.h
cvs rdiff -u -r1.12.4.4 -r1.12.4.5 src/sys/arch/xen/x86/x86_xpmap.c
cvs rdiff -u -r1.4.12.3 -r1.4.12.4 src/sys/arch/xen/xen/xen_machdep.c
cvs rdiff -u -r1.31.2.3 -r1.31.2.4 src/sys/arch/xen/xen/xencons.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.21.2.3 src/sys/arch/x86/include/pmap.h:1.21.2.4
--- src/sys/arch/x86/include/pmap.h:1.21.2.3	Thu Jul 23 23:31:36 2009
+++ src/sys/arch/x86/include/pmap.h	Fri Jul 24 11:30:28 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.21.2.3 2009/07/23 23:31:36 jym Exp $	*/
+/*	$NetBSD: pmap.h,v 1.21.2.4 2009/07/24 11:30:28 jym Exp $	*/
 
 /*
  *
@@ -354,6 +354,34 @@
 
 #ifdef XEN
 
+#ifdef PAE
+/*
+ * Under PAE, Xen handles our recursive mappings to the L2 shadow pages
+ * erroneously during a restore (the last entry of the PDIR_SLOT_PTE).
+ * This pages are found in two places:
+ * - the used ones are found in the pmaps list
+ * - the unused ones (but still valid from a Xen's point of view) are cached
+ *   inside the pmap_pdp_cache pool.
+ * This list is not protected by locks, as it is expected to be accessed only
+ * during pmap_create()/pmap_destroy(), and save/restore code, which
+ * cannot run concurrently.
+struct l2_pdirpte {
+	SLIST_ENTRY(l2_pinned) l2_pdirpte_list;
+	paddr_t slot_pte;
+	paddr_t slot_pte_content;
+};
+ */
+
+/*
+ * Head of the list of all pages pinned as L2 and containing valid entry
+ * in PDIR_SLOT_PTE
+SLIST_HEAD(l2_pdirpte_head, l2_pdirpte);
+ */
+
+void	pmap_map_shadow_entries(void);
+void	pmap_unmap_shadow_entries(void);
+#endif /* PAE */
+
 #define XPTE_MASK	L1_FRAME
 /* XPTE_SHIFT = L1_SHIFT - log2(sizeof(pt_entry_t)) */
 #if defined(__x86_64__) || defined(PAE)

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.77.2.4 src/sys/arch/x86/x86/pmap.c:1.77.2.5
--- src/sys/arch/x86/x86/pmap.c:1.77.2.4	Thu Jul 23 23:31:37 2009
+++ src/sys/arch/x86/x86/pmap.c	Fri Jul 24 11:30:28 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.77.2.4 2009/07/23 23:31:37 jym Exp $	*/
+/*	$NetBSD: pmap.c,v 1.77.2.5 2009/07/24 11:30:28 jym Exp $	*/
 
 /*
  * Copyright (c) 2007 Manuel Bouyer.
@@ -154,7 +154,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.77.2.4 2009/07/23 23:31:37 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.77.2.5 2009/07/24 11:30:28 jym Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -557,6 +557,12 @@
 	.pa_free = pmap_pdp_free,
 	.pa_pagesz = PAGE_SIZE * PDP_SIZE,
 };
+
+#ifdef XEN
+/* pool for allocation of the structures tracking L2 pinned shadow pages */
+//static struct pool_cache l2_pdirpte_cache;
+#endif /* XEN */
+
 #endif /* PAE */
 
 void *vmmap; /* XXX: used by mem.c... it should really uvm_map_reserve it */
@@ -752,13 +758,14 @@
 	for (i = 0; i < PDP_SIZE; i++) {
 		pmap_pte_set(&APDP_PDE[i], 0);
 #ifdef PAE
-		/* clear shadow entry too */
+		/* clear current pmap shadow entries too */
     		pmap_pte_set(&APDP_PDE_SHADOW[i], 0);
 #endif
 	}
 
 }
 
+#ifdef XEN3
 /*
  * Flush all APDP entries found in pmaps
  * Required during Xen save/restore operations, as it does not
@@ -767,26 +774,102 @@
 void
 pmap_unmap_all_apdp_pdes(void) {
 
-	// XXX JYM PAE
-
+	int i;
 	int s;
 	struct pmap *pm;
 
 	s = splvm();
 
+#ifdef PAE
+	/*
+	 * For PAE, there are two places where alternative recursive mappings
+	 * could be found: in the L2 shadow pages, and the "real" L2 kernel
+	 * page (pmap_kl2pd), which is unique and static.
+	 * We first clear the APDP for the current pmap. As L2 kernel page is
+	 * unique, we only need to do it once for all pmaps.
+	 */
+	pmap_unmap_apdp_pde();
+#endif
+
+	mutex_enter(&pmaps_lock);
+	/*
+	 * Set APDP entries to 0 in all pmaps.
+	 * Note that for PAE kernels, this only clears the APDP entries
+	 * found in the L2 shadow pages, as pmap_pdirpa() is used to obtain
+	 * the PA of the pmap->pm_pdir[] pages (forming the 4 contiguous
+	 * pages of PAE PD: 3 for user space, 1 for the L2 kernel shadow page)
+	 */
+	LIST_FOREACH(pm, &pmaps, pm_list) {
+		for (i = 0; i < PDP_SIZE; i++) {
+			xpq_queue_pte_update(
+			    xpmap_ptom(pmap_pdirpa(pm, PDIR_SLOT_APTE + i)), 0);
+		}
+	}
+	mutex_exit(&pmaps_lock);
+
+	xpq_flush_queue();
+
+	splx(s);
+
+}
+
+#ifdef PAE
+/*
+ * NetBSD uses L2 shadow pages to support PAE with Xen. However, Xen does not
+ * handle them correctly during save/restore, leading to incorrect page
+ * tracking and pinning during restore.
+ * For save/restore to succeed, two functions are introduced:
+ * - pmap_map_shadow_entries(), used by resume code to set the last entry
+ *   of PDIR_SLOT_PTE so that it points to the correct L2 shadow page
+ *   entries to their correct values, so that pmap works again.
+ * - pmap_unmap_shadow_entries(), used by suspend code to clear all
+ *   PDIR_SLOT_PTE entries pointing to L2 shadow entries
+ */ 
+void
+pmap_map_shadow_entries(void) {
+
+	struct pmap *pm;
+
 	mutex_enter(&pmaps_lock);
+
 	LIST_FOREACH(pm, &pmaps, pm_list) {
 		xpq_queue_pte_update(
-		    xpmap_ptom(pmap_pdirpa(pm, PDIR_SLOT_APTE)),
-		    0);
+		    xpmap_ptom(pmap_pdirpa(pm, PDIR_SLOT_PTE + 3)),
+		    xpmap_ptom(pmap_pdirpa(pm, PDIR_SLOT_KERN)) | PG_V);
 	}
+
+	mutex_exit(&pmaps_lock);
+
+	xpq_queue_pte_update(
+	    xpmap_ptom(pmap_pdirpa(pmap_kernel(), PDIR_SLOT_PTE + 3)),
+	    xpmap_ptom(pmap_pdirpa(pmap_kernel(), PDIR_SLOT_KERN)) | PG_V);
+
 	xpq_flush_queue();
+}
+
+void
+pmap_unmap_shadow_entries(void) {
+
+	struct pmap *pm;
+
+	mutex_enter(&pmaps_lock);
+
+	LIST_FOREACH(pm, &pmaps, pm_list) {
+		xpq_queue_pte_update(
+		    xpmap_ptom(pmap_pdirpa(pm, PDIR_SLOT_PTE + 3)), 0);
+	}
 
 	mutex_exit(&pmaps_lock);
 
-	splx(s);
+	/* do it for pmap_kernel() too! */
+	xpq_queue_pte_update(
+	    xpmap_ptom(pmap_pdirpa(pmap_kernel(), PDIR_SLOT_PTE + 3)), 0);
+
+	xpq_flush_queue();
 
 }
+#endif /* PAE */
+#endif /* XEN3 */
 
 
 static void
@@ -1569,7 +1652,7 @@
 	HYPERVISOR_update_va_mapping(xen_dummy_user_pgd + KERNBASE,
 	    pmap_pa2pte(xen_dummy_user_pgd) | PG_u | PG_V, UVMF_INVLPG);
 	/* Pin as L4 */
-	xpq_queue_pin_table(xpmap_ptom_masked(xen_dummy_user_pgd));
+	xpq_queue_pin_l4_table(xpmap_ptom_masked(xen_dummy_user_pgd));
 #endif /* __x86_64__ */
 	idt_vaddr = virtual_avail;                      /* don't need pte */
 	idt_paddr = avail_start;                        /* steal a page */
@@ -1630,6 +1713,10 @@
 	pool_cache_bootstrap(&pmap_cache, sizeof(struct pmap), 0, 0, 0,
 	    "pmappl", NULL, IPL_NONE, NULL, NULL, NULL);
 #ifdef PAE
+#ifdef XEN
+	//pool_cache_bootstrap(&l2_pdirpte_cache, sizeof(struct l2_pdirpte), 0, 0,
+	//    0, "l2_pdirptepl", NULL, IPL_NONE, NULL, NULL, NULL);
+#endif /* XEN */
 	pool_cache_bootstrap(&pmap_pdp_cache, PAGE_SIZE * PDP_SIZE, 0, 0, 0,
 	    "pdppl", &pmap_pdp_allocator, IPL_NONE,
 	    pmap_pdp_ctor, pmap_pdp_dtor, NULL);
@@ -2222,12 +2309,12 @@
 		if (i == l2tol3(PDIR_SLOT_PTE))
 			continue;
 #endif
-		xpq_queue_pin_table(xpmap_ptom_masked(pdirpa));
+		xpq_queue_pin_l2_table(xpmap_ptom_masked(pdirpa));
 	}
 #ifdef PAE
 	object = ((vaddr_t)pdir) + PAGE_SIZE  * l2tol3(PDIR_SLOT_PTE);
 	(void)pmap_extract(pmap_kernel(), object, &pdirpa);
-	xpq_queue_pin_table(xpmap_ptom_masked(pdirpa));
+	xpq_queue_pin_l2_table(xpmap_ptom_masked(pdirpa));
 #endif
 	xpq_flush_queue();
 	splx(s);
@@ -2312,8 +2399,12 @@
 {
 	struct pmap *pmap;
 	int i;
+#ifdef PAE
+	//struct l2_pdirpte *l2s;
+#endif /* PAE */
 
 	pmap = pool_cache_get(&pmap_cache, PR_WAITOK);
+	//l2p  = pool_cache_get(&l2_pdirpte_cache, PR_WAITOK);
 
 	/* init uvm_object */
 	for (i = 0; i < PTP_LEVELS - 1; i++) {
@@ -2354,6 +2445,14 @@
 	for (i = 0; i < PDP_SIZE; i++)
 		pmap->pm_pdirpa[i] =
 		    pmap_pte2pa(pmap->pm_pdir[PDIR_SLOT_PTE + i]);
+
+	/*
+	 * We now have an L2 page with a valid PDIR_SLOT_PTE pointing
+	 * to a shadow L2, so track it
+	l2p->slot_pte = pdirpa;
+	l2p->slot_pte_content = pmap_pte2pa(pmap->pm_pdir[PDIR_SLOT_PTE + i]);
+	 */
+
 #else
 	pmap->pm_pdirpa = pmap_pte2pa(pmap->pm_pdir[PDIR_SLOT_PTE]);
 #endif

Index: src/sys/arch/xen/include/xenpmap.h
diff -u src/sys/arch/xen/include/xenpmap.h:1.21.8.2 src/sys/arch/xen/include/xenpmap.h:1.21.8.3
--- src/sys/arch/xen/include/xenpmap.h:1.21.8.2	Wed May 13 17:18:50 2009
+++ src/sys/arch/xen/include/xenpmap.h	Fri Jul 24 11:30:28 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: xenpmap.h,v 1.21.8.2 2009/05/13 17:18:50 jym Exp $	*/
+/*	$NetBSD: xenpmap.h,v 1.21.8.3 2009/07/24 11:30:28 jym Exp $	*/
 
 /*
  *
@@ -45,10 +45,34 @@
 void xpq_flush_queue(void);
 void xpq_queue_set_ldt(vaddr_t, uint32_t);
 void xpq_queue_tlb_flush(void);
-void xpq_queue_pin_table(paddr_t);
+void xpq_queue_pin_table(paddr_t, unsigned int);
 void xpq_queue_unpin_table(paddr_t);
 int  xpq_update_foreign(paddr_t, pt_entry_t, int);
 
+static void inline
+xpq_queue_pin_l1_table(paddr_t pa) {
+	xpq_queue_pin_table(pa, MMUEXT_PIN_L1_TABLE);
+}
+
+static void inline
+xpq_queue_pin_l2_table(paddr_t pa) {
+	xpq_queue_pin_table(pa, MMUEXT_PIN_L2_TABLE);
+}
+
+#if defined(PAE) || defined(__x86_64__)
+static void inline
+xpq_queue_pin_l3_table(paddr_t pa) {
+	xpq_queue_pin_table(pa, MMUEXT_PIN_L3_TABLE);
+}
+#endif
+
+#if defined(__x86_64__)
+static void inline
+xpq_queue_pin_l4_table(paddr_t pa) {
+	xpq_queue_pin_table(pa, MMUEXT_PIN_L4_TABLE);
+}
+#endif
+
 extern unsigned long *xpmap_phys_to_machine_mapping;
 
 /*   

Index: src/sys/arch/xen/x86/x86_xpmap.c
diff -u src/sys/arch/xen/x86/x86_xpmap.c:1.12.4.4 src/sys/arch/xen/x86/x86_xpmap.c:1.12.4.5
--- src/sys/arch/xen/x86/x86_xpmap.c:1.12.4.4	Thu Jul 23 23:31:37 2009
+++ src/sys/arch/xen/x86/x86_xpmap.c	Fri Jul 24 11:30:28 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: x86_xpmap.c,v 1.12.4.4 2009/07/23 23:31:37 jym Exp $	*/
+/*	$NetBSD: x86_xpmap.c,v 1.12.4.5 2009/07/24 11:30:28 jym Exp $	*/
 
 /*
  * Copyright (c) 2006 Mathieu Ropert <m...@adviseo.fr>
@@ -79,7 +79,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.12.4.4 2009/07/23 23:31:37 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.12.4.5 2009/07/24 11:30:28 jym Exp $");
 
 #include "opt_xen.h"
 #include "opt_ddb.h"
@@ -298,40 +298,21 @@
 }
 
 void
-xpq_queue_pin_table(paddr_t pa)
-{
-	struct mmuext_op op;
-	xpq_flush_queue();
-
-	XENPRINTK2(("xpq_queue_pin_table: 0x%" PRIx64 " 0x%" PRIx64 "\n",
-	    (int64_t)pa, (int64_t)pa));
-	op.arg1.mfn = pa >> PAGE_SHIFT;
-
-#if defined(__x86_64__)
-	op.cmd = MMUEXT_PIN_L4_TABLE;
-#else
-	op.cmd = MMUEXT_PIN_L2_TABLE;
-#endif
-	if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
-		panic("xpq_queue_pin_table");
-}
+xpq_queue_pin_table(paddr_t pa, unsigned int level) {
 
-#ifdef PAE
-static void
-xpq_queue_pin_l3_table(paddr_t pa)
-{
 	struct mmuext_op op;
 	xpq_flush_queue();
 
-	XENPRINTK2(("xpq_queue_pin_l2_table: 0x%" PRIx64 " 0x%" PRIx64 "\n",
-	    (int64_t)pa, (int64_t)pa));
+	XENPRINTK2(("xpq_queue_pin_table: level %u %#"PRIx64"\n",
+	    level, (int64_t)pa));
+
 	op.arg1.mfn = pa >> PAGE_SHIFT;
+	op.cmd = level;
 
-	op.cmd = MMUEXT_PIN_L3_TABLE;
 	if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
-		panic("xpq_queue_pin_table");
+		panic("xpq_queue_pin_table: level %u %#"PRIx64"\n",
+		    level, (int64_t)pa);
 }
-#endif
 
 void
 xpq_queue_unpin_table(paddr_t pa)
@@ -934,18 +915,18 @@
 			continue;
 #if 0
 		__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr));
-		xpq_queue_pin_table(xpmap_ptom_masked(addr));
+		xpq_queue_pin_l2_table(xpmap_ptom_masked(addr));
 #endif
 	}
 	if (final) {
 		addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE;
 		__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr));
-		xpq_queue_pin_table(xpmap_ptom_masked(addr));
+		xpq_queue_pin_l2_table(xpmap_ptom_masked(addr));
 	}
 #if 0
 	addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE;
 	__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr));
-	xpq_queue_pin_table(xpmap_ptom_masked(addr));
+	xpq_queue_pin_l2_table(xpmap_ptom_masked(addr));
 #endif
 #else /* PAE */
 	/* recursive entry in higher-level PD */
@@ -967,8 +948,10 @@
 	__PRINTK(("pin PGD\n"));
 #ifdef PAE
 	xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE));
+#elif __x86_64__
+	xpq_queue_pin_l4_table(xpmap_ptom_masked(new_pgd - KERNBASE));
 #else
-	xpq_queue_pin_table(xpmap_ptom_masked(new_pgd - KERNBASE));
+	xpq_queue_pin_l2_table(xpmap_ptom_masked(new_pgd - KERNBASE));
 #endif
 #ifdef __i386__
 	/* Save phys. addr of PDP, for libkvm. */

Index: src/sys/arch/xen/xen/xen_machdep.c
diff -u src/sys/arch/xen/xen/xen_machdep.c:1.4.12.3 src/sys/arch/xen/xen/xen_machdep.c:1.4.12.4
--- src/sys/arch/xen/xen/xen_machdep.c:1.4.12.3	Sun May 31 20:15:37 2009
+++ src/sys/arch/xen/xen/xen_machdep.c	Fri Jul 24 11:30:28 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: xen_machdep.c,v 1.4.12.3 2009/05/31 20:15:37 jym Exp $	*/
+/*	$NetBSD: xen_machdep.c,v 1.4.12.4 2009/07/24 11:30:28 jym Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -63,7 +63,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xen_machdep.c,v 1.4.12.3 2009/05/31 20:15:37 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xen_machdep.c,v 1.4.12.4 2009/07/24 11:30:28 jym Exp $");
 
 #include "opt_xen.h"
 
@@ -293,6 +293,10 @@
 	 */
 	pmap_unmap_all_apdp_pdes();
 
+#ifdef PAE
+	pmap_unmap_shadow_entries();
+#endif
+
 	/*
 	 * save/restore code does not translate these MFNs to their
 	 * associated PFNs, so we must do it
@@ -326,6 +330,10 @@
 		HYPERVISOR_crash();
 	}
 
+#ifdef PAE
+	pmap_map_shadow_entries();
+#endif
+
 	if (xen_start_info.nr_pages != physmem) {
 		/*
 		 * XXX JYM for now, we crash - fix it with balloon when

Index: src/sys/arch/xen/xen/xencons.c
diff -u src/sys/arch/xen/xen/xencons.c:1.31.2.3 src/sys/arch/xen/xen/xencons.c:1.31.2.4
--- src/sys/arch/xen/xen/xencons.c:1.31.2.3	Thu Jul 23 23:31:38 2009
+++ src/sys/arch/xen/xen/xencons.c	Fri Jul 24 11:30:28 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: xencons.c,v 1.31.2.3 2009/07/23 23:31:38 jym Exp $	*/
+/*	$NetBSD: xencons.c,v 1.31.2.4 2009/07/24 11:30:28 jym Exp $	*/
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -63,7 +63,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xencons.c,v 1.31.2.3 2009/07/23 23:31:38 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xencons.c,v 1.31.2.4 2009/07/24 11:30:28 jym Exp $");
 
 #include "opt_xen.h"
 
@@ -75,6 +75,7 @@
 #include <sys/device.h>
 #include <sys/conf.h>
 #include <sys/kauth.h>
+#include <sys/kernel.h>
 
 #include <machine/stdarg.h>
 #include <xen/xen.h>
@@ -228,25 +229,21 @@
 
 	int evtch;
 
-	if (xendomain_is_dom0()) {
-		evtch = unbind_virq_from_evtch(VIRQ_CONSOLE);
-		hypervisor_mask_event(evtch);
-		if (event_remove_handler(evtch, xencons_intr,
-		    xencons_console_device) != 0)
-			aprint_error_dev(dev,
-			    "can't remove handler: xencons_intr\n");
-	} else {
+	/* dom0 console should not be suspended */
+	if (!xendomain_is_dom0()) {
 #ifdef XEN3
 		evtch = xen_start_info.console_evtchn;
 		hypervisor_mask_event(evtch);
 		if (event_remove_handler(evtch, xencons_handler,
-		    xencons_console_device) != 0)
+		    xencons_console_device) != 0) {
 			aprint_error_dev(dev,
 			    "can't remove handler: xencons_handler\n");
+		}
 #endif
+
+		aprint_verbose_dev(dev, "removed event channel %d\n", evtch);
 	}
 
-	aprint_verbose_dev(dev, "removed event channel %d\n", evtch);
 
 	return true;
 }
@@ -257,16 +254,18 @@
 	int evtch = -1;
 
 	if (xendomain_is_dom0()) {
-		evtch = bind_virq_to_evtch(VIRQ_CONSOLE);
-		if (event_set_handler(evtch, xencons_intr,
-		    xencons_console_device, IPL_TTY, "xencons") != 0)
-			aprint_error_dev(dev, "can't register xencons_intr\n");
+	/* dom0 console resume is required only during first start-up */
+		if (cold) {
+			evtch = bind_virq_to_evtch(VIRQ_CONSOLE);
+			event_set_handler(evtch, xencons_intr,
+			    xencons_console_device, IPL_TTY, "xencons");
+		}
 	} else {
 #ifdef XEN3
 		evtch = xen_start_info.console_evtchn;
-		if (event_set_handler(evtch, xencons_handler,
-		    xencons_console_device, IPL_TTY, "xencons") != 0)
-			aprint_error_dev(dev, "can't register xencons_handler\n");
+		event_set_handler(evtch, xencons_handler,
+		    xencons_console_device, IPL_TTY, "xencons");
+
 #else
 		(void)ctrl_if_register_receiver(CMSG_CONSOLE,
 		    xencons_rx, 0);

Reply via email to