[Lguest] kernel BUG at arch/x86/kernel/irq_32.c

Rusty Russell rusty at rustcorp.com.au
Fri Oct 24 14:15:00 EST 2008


On Thursday 23 October 2008 00:15:00 Tiago Maluta wrote:
> -- kernel  --
>
> Kernel: 2.6.27-06509-g2515ddc-dirty
> Environment: x86 (32-bits)
> config attached

Hit this one too...

Here are the two patches which really fix the problems:

lguest: fix early_ioremap.

dmi_scan_machine breaks under lguest:
	lguest: unhandled trap 14 at 0xc04edeae (0xffa00000)

This is because we use current_cr3 for the read_cr3() paravirt
function, and it isn't set until the first cr3 change.  We got away
with it until this happened.

Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
---
 arch/x86/lguest/boot.c |   29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff -r 7e38804a58b5 arch/x86/lguest/boot.c
--- a/arch/x86/lguest/boot.c	Thu Oct 23 12:07:04 2008 +1100
+++ b/arch/x86/lguest/boot.c	Thu Oct 23 14:30:20 2008 +1100
@@ -367,10 +367,9 @@ static void lguest_cpuid(unsigned int *a
  * lazily after a task switch, and Linux uses that gratefully, but wouldn't a
  * name like "FPUTRAP bit" be a little less cryptic?
  *
- * We store cr0 (and cr3) locally, because the Host never changes it.  The
- * Guest sometimes wants to read it and we'd prefer not to bother the Host
- * unnecessarily. */
-static unsigned long current_cr0, current_cr3;
+ * We store cr0 locally because the Host never changes it.  The Guest sometimes
+ * wants to read it and we'd prefer not to bother the Host unnecessarily. */
+static unsigned long current_cr0;
 static void lguest_write_cr0(unsigned long val)
 {
 	lazy_hcall(LHCALL_TS, val & X86_CR0_TS, 0, 0);
@@ -399,17 +398,23 @@ static unsigned long lguest_read_cr2(voi
 	return lguest_data.cr2;
 }
 
+/* See lguest_set_pte() below. */
+static bool cr3_changed = false;
+
 /* cr3 is the current toplevel pagetable page: the principle is the same as
- * cr0.  Keep a local copy, and tell the Host when it changes. */
+ * cr0.  Keep a local copy, and tell the Host when it changes.  The only
+ * difference is that our local copy is in lguest_data because the Host needs
+ * to set it upon our initial hypercall. */
 static void lguest_write_cr3(unsigned long cr3)
 {
+	lguest_data.pgdir = cr3;
 	lazy_hcall(LHCALL_NEW_PGTABLE, cr3, 0, 0);
-	current_cr3 = cr3;
+	cr3_changed = true;
 }
 
 static unsigned long lguest_read_cr3(void)
 {
-	return current_cr3;
+	return lguest_data.pgdir;
 }
 
 /* cr4 is used to enable and disable PGE, but we don't care. */
@@ -498,13 +503,13 @@ static void lguest_set_pmd(pmd_t *pmdp, 
  * to forget all of them.  Fortunately, this is very rare.
  *
  * ... except in early boot when the kernel sets up the initial pagetables,
- * which makes booting astonishingly slow.  So we don't even tell the Host
- * anything changed until we've done the first page table switch. */
+ * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
+ * the Host anything changed until we've done the first page table switch,
+ * which brings boot back to 0.25 seconds. */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
 	*ptep = pteval;
-	/* Don't bother with hypercall before initial setup. */
-	if (current_cr3)
+	if (cr3_changed)
 		lazy_hcall(LHCALL_FLUSH_TLB, 1, 0, 0);
 }
 
@@ -521,7 +526,7 @@ static void lguest_flush_tlb_single(unsi
 static void lguest_flush_tlb_single(unsigned long addr)
 {
 	/* Simply set it to zero: if it was not, it will fault back in. */
-	lazy_hcall(LHCALL_SET_PTE, current_cr3, addr, 0);
+	lazy_hcall(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0);
 }
 
 /* This is what happens after the Guest has removed a large number of entries.


lguest: fix irq vectors.

	do_IRQ: cannot handle IRQ -1 vector 0x20 cpu 0
	------------[ cut here ]------------
	kernel BUG at arch/x86/kernel/irq_32.c:219!

We're not ISA: we have a 1:1 mapping from vectors to irqs.

Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
---
 arch/x86/lguest/boot.c |    3 +++
 1 file changed, 3 insertions(+)

diff -r 7e38804a58b5 arch/x86/lguest/boot.c
--- a/arch/x86/lguest/boot.c	Thu Oct 23 12:07:04 2008 +1100
+++ b/arch/x86/lguest/boot.c	Thu Oct 23 14:30:20 2008 +1100
@@ -581,6 +586,9 @@ static void __init lguest_init_IRQ(void)
 
 	for (i = 0; i < LGUEST_IRQS; i++) {
 		int vector = FIRST_EXTERNAL_VECTOR + i;
+		/* Some systems map "vectors" to interrupts weirdly.  Lguest has
+		 * a straightforward 1 to 1 mapping, so force that here. */
+		__get_cpu_var(vector_irq)[vector] = i;
 		if (vector != SYSCALL_VECTOR) {
 			set_intr_gate(vector, interrupt[vector]);
 			set_irq_chip_and_handler_name(i, &lguest_irq_controller,




More information about the Lguest mailing list