diff -r 7e3cf18ea7a6 -r 62fdd3c03dac arch/i386/Kconfig
--- a/arch/i386/Kconfig	Thu Jan 11 19:57:19 2007 -0500
+++ b/arch/i386/Kconfig	Thu Jan 18 12:32:25 2007 -0500
@@ -212,7 +212,7 @@ source "arch/i386/paravirt-xen/Kconfig"
 
 config LGUEST
 	tristate "Linux hypervisor example code"
-	depends on X86 && PARAVIRT && EXPERIMENTAL && !SMP && !X86_PAE
+	depends on X86 && PARAVIRT && EXPERIMENTAL && !X86_PAE
 	select LGUEST_GUEST
 	select HVC_DRIVER
 	---help---
diff -r 7e3cf18ea7a6 -r 62fdd3c03dac arch/i386/kernel/lguest.c
--- a/arch/i386/kernel/lguest.c	Thu Jan 11 19:57:19 2007 -0500
+++ b/arch/i386/kernel/lguest.c	Thu Jan 18 12:32:25 2007 -0500
@@ -209,6 +209,14 @@ static fastcall unsigned long lguest_api
 {
 	return 0;
 }
+
+static void lguest_setup_boot_clock(void)
+{
+}
+
+static void lguest_setup_secondary_clock(void)
+{
+}
 #endif
 
 /* We move eflags word to lguest_page.irq_enabled to restore interrupt
@@ -419,6 +427,8 @@ static __attribute_used__ __init void lg
 	paravirt_ops.apic_write = lguest_apic_write;
 	paravirt_ops.apic_write_atomic = lguest_apic_write_atomic;
 	paravirt_ops.apic_read = lguest_apic_read;
+	paravirt_ops.setup_boot_clock = lguest_setup_boot_clock;
+	paravirt_ops.setup_secondary_clock = lguest_setup_secondary_clock;
 #endif
 	paravirt_ops.load_idt = lguest_load_idt;
 	paravirt_ops.iret = lguest_iret;
diff -r 7e3cf18ea7a6 -r 62fdd3c03dac arch/i386/kernel/smp.c
--- a/arch/i386/kernel/smp.c	Thu Jan 11 19:57:19 2007 -0500
+++ b/arch/i386/kernel/smp.c	Thu Jan 18 12:32:25 2007 -0500
@@ -478,6 +478,7 @@ void flush_tlb_all(void)
 {
 	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
 }
+EXPORT_SYMBOL_GPL(flush_tlb_all);
 
 /*
  * this function sends a 'reschedule' IPI to another CPU.
diff -r 7e3cf18ea7a6 -r 62fdd3c03dac drivers/lguest/core.c
--- a/drivers/lguest/core.c	Thu Jan 11 19:57:19 2007 -0500
+++ b/drivers/lguest/core.c	Thu Jan 18 12:32:25 2007 -0500
@@ -602,20 +602,18 @@ static void __init setup_hypervisor(stru
 static void __init setup_hypervisor(struct hypervisor *lguest)
 {
 	struct desc_struct lguest_cs, lguest_ds;
-	unsigned int i;
-
+	unsigned int i, cpu = get_cpu();
+	
 	/* Insert lguest entries in GDT (copy kernel segments). */
-	lguest_cs = get_cpu_gdt_table(smp_processor_id())[GDT_ENTRY_KERNEL_CS];
-	lguest_ds = get_cpu_gdt_table(smp_processor_id())[GDT_ENTRY_KERNEL_DS];
+	lguest_cs = get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS];
+	lguest_ds = get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_DS];
+	put_cpu();
+
 	for_each_possible_cpu(i) {
 		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = lguest_cs;
 		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = lguest_ds;
 	}
 
-	/* Tell hypervisor stub about our GDT and IDT. */
-	*__lguest(master_gdt) = __get_cpu_var(cpu_gdt_descr);
-	asm("sidt %0":"=m"(*__lguest(master_idt)));
-
 	/* Entry point into hypervisor. */
 	lguest_entry.offset = (long)__lguest(switch_to_guest);
 	lguest_entry.segment = LGUEST_CS;
@@ -623,11 +621,8 @@ static void __init setup_hypervisor(stru
 
 #define STRUCT_LGUEST_ELEM_SIZE(elem) sizeof(((struct lguest_guest *)0)->elem)
 
-static int __init init(void)
-{
-	struct hypervisor *lguest;
-	int err;
-
+static void __attribute__((unused)) verify_offsets(void)
+{
 	BUILD_BUG_ON(LGUEST_TSS_OFF != offsetof(struct lguest_guest, tss));
 	BUILD_BUG_ON(LGUEST_TSS_SIZE != STRUCT_LGUEST_ELEM_SIZE(tss));
 	BUILD_BUG_ON(LGUEST_GDT_OFF != offsetof(struct lguest_guest, gdt));
@@ -637,12 +632,35 @@ static int __init init(void)
 	BUILD_BUG_ON(LGUEST_IDT_OFF
 		     != offsetof(struct lguest_guest, idt));
 	BUILD_BUG_ON(LGUEST_IDTABLE_SIZE != STRUCT_LGUEST_ELEM_SIZE(idt_table));
+	BUILD_BUG_ON(LGUEST_MASTER_OFF
+		     != offsetof(struct lguest_guest, master));
+	BUILD_BUG_ON(LGUEST_MASTER_GDT_OFF
+	             != offsetof(struct lguest_guest, master)
+	             + offsetof(struct lguest_master, gdt));
+	BUILD_BUG_ON(LGUEST_MASTER_IDT_OFF
+	             != offsetof(struct lguest_guest, master)
+	             + offsetof(struct lguest_master, idt));
+	BUILD_BUG_ON(LGUEST_MASTER_PGDIR_OFF
+	             != offsetof(struct lguest_guest, master)
+	             + offsetof(struct lguest_master, pgdir));
+	BUILD_BUG_ON(LGUEST_MASTER_STKP_OFF
+	             != offsetof(struct lguest_guest, master)
+	             + offsetof(struct lguest_master, stackptr));
+	BUILD_BUG_ON(LGUEST_MASTER_CR4_OFF
+	             != offsetof(struct lguest_guest, master)
+	             + offsetof(struct lguest_master, cr4));
 	BUILD_BUG_ON(LGUEST_REGS_OFF
 		     != offsetof(struct lguest_guest, regs));
 	BUILD_BUG_ON(LGUEST_TRAPNUM_OFF != offsetof(struct lguest_guest, regs)
 		     + offsetof(struct lguest_regs, trapnum));
 	BUILD_BUG_ON(LGUEST_ERRCODE_OFF != offsetof(struct lguest_guest, regs)
 		     + offsetof(struct lguest_regs, errcode));
+}
+
+static int __init init(void)
+{
+	struct hypervisor *lguest;
+	int err;
 
 	if (paravirt_enabled())
 		return -EPERM;
@@ -665,6 +683,8 @@ static int __init init(void)
 		free_reservemem_pages();
 		return -ENOMEM;
 	}
+	
+	printk("LGUEST module: %s %s\n", __DATE__, __TIME__);
 	return 0;
 }
 
diff -r 7e3cf18ea7a6 -r 62fdd3c03dac drivers/lguest/device.c
--- a/drivers/lguest/device.c	Thu Jan 11 19:57:19 2007 -0500
+++ b/drivers/lguest/device.c	Thu Jan 18 12:32:25 2007 -0500
@@ -14,13 +14,20 @@ static struct lguest_guest *setup_guest(
 	const long *idt = __lguest(default_idt_entries);
 	struct lguest_regs *regs;
 	struct desc_struct *gdt_table;
+	struct lguest_master *master;
 
 	guest = &__lguest(lguest_guests)[num];
+	master = &guest->master;
 
 	/* Other guest's GDT has kernel CS and DS. */
 	gdt_table = get_cpu_gdt_table(get_cpu());
 	guest->gdt_table[GDT_ENTRY_KERNEL_CS] = gdt_table[GDT_ENTRY_KERNEL_CS];
 	guest->gdt_table[GDT_ENTRY_KERNEL_DS] = gdt_table[GDT_ENTRY_KERNEL_DS];
+	
+	/* Host state to be restored after the guest returns. */
+	asm("sidt %0":"=m"(master->idt));
+	master->gdt = __get_cpu_var(cpu_gdt_descr);
+
 	put_cpu();
 	if (!fixup_gdt_table(guest->gdt_table, ARRAY_SIZE(guest->gdt_table),
 			     &guest->tss))
diff -r 7e3cf18ea7a6 -r 62fdd3c03dac drivers/lguest/hypervisor.S
--- a/drivers/lguest/hypervisor.S	Thu Jan 11 19:57:19 2007 -0500
+++ b/drivers/lguest/hypervisor.S	Thu Jan 18 12:32:25 2007 -0500
@@ -1,31 +1,6 @@
 /* This code sits in the hypervisor core to do the low-level guest<->host switch */
 #include <linux/linkage.h>
 #include "lguest.h"
-
-ALIGN
-/* FIXME: to be SMP-safe, these need to be per-cpu or in lguest_guest struct */
-	.word	0 # Align gdt address correctly.
-.globl master_gdt
-master_gdt:
-	.word	0
-	.long	0
-
-	.word	0 # Align idt address correctly.
-.globl master_idt
-master_idt:
-	.word	0
-	.long	0
-master_pgdir:
-	.long	0
-
-master_stackptr:
-	.long	0
-
-master_cr4:
-	.long	0
-
-currentdom:
-	.long	0
 
 .text
 
@@ -48,23 +23,23 @@ ENTRY(switch_to_guest)
 	pushl	%ss
 	SAVE_REGS
 	/* Save old stack, switch to guest's stack. */
-	movl	%esp, master_stackptr
+	movl	%esp, LGUEST_MASTER_STKP_OFF(%eax)
 	movl	%eax, %esp
+	/* 'currentdom' will be at: %esp-$LGUEST_REGS_OFF */
 	addl	$LGUEST_REGS_OFF, %esp
 	/* Switch to guest's GDT, IDT. */
 	lgdt	LGUEST_GDT_OFF(%eax)
 	lidt	LGUEST_IDT_OFF(%eax)
 	/* Now we are running guest. */
-	movl	%eax, currentdom
 	/* Save page table top. */
 	movl	%cr3, %ebx
-	movl	%ebx, master_pgdir
+	movl	%ebx, LGUEST_MASTER_PGDIR_OFF(%eax)
 	/* Set master's TSS to available (clear byte 5 bit 2). */
-	movl	(master_gdt+2), %ebx
+	movl	(LGUEST_MASTER_GDT_OFF+2)(%eax), %ebx
 	andb	$0xFD, (GDT_ENTRY_TSS*8 + 5)(%ebx)
 	/* Turn off PGE */
 	movl	%cr4, %ebx
-	movl	%ebx, master_cr4
+	movl	%ebx, LGUEST_MASTER_CR4_OFF(%eax)
 	andl	$0xFFFFFF7F, %ebx
 	movl	%ebx, %cr4
 	/* Switch to domU page tables */
@@ -102,27 +77,26 @@ ENTRY(switch_to_guest)
 	/* Load lguest ds segment for convenience. */			\
 	movl	$(LGUEST_DS), %eax;					\
 	movl	%eax, %ds;						\
+	/* Now figure out who we are */					\
+	movl	%esp, %eax;						\
+	subl	$LGUEST_REGS_OFF, %eax;					\
 	/* Turn PGE back on */;						\
-	movl	master_cr4, %eax;					\
-	movl	%eax, %cr4;						\
+	movl	LGUEST_MASTER_CR4_OFF(%eax), %ebx;			\
+	movl	%ebx, %cr4;						\
 	/* Switch to host page tables (GDT, IDT and stack are in host   \
 	   mem, so need this first) */					\
-	movl	master_pgdir, %eax;					\
-	movl	%eax, %cr3;						\
-	/* Now figure out who we are */					\
-	movl	currentdom, %eax;					\
+	movl	LGUEST_MASTER_PGDIR_OFF(%eax), %ebx;			\
+	movl	%ebx, %cr3;						\
 	/* Set domU's TSS to available (clear byte 5 bit 2). */		\
 	andb	$0xFD, (LGUEST_GDTABLE_OFF+GDT_ENTRY_TSS*8+5)(%eax);	\
 	/* Switch to master's GDT & IDT. */				\
-	lgdt	master_gdt;						\
-	lidt	master_idt;						\
+	lgdt	LGUEST_MASTER_GDT_OFF(%eax);				\
+	lidt	LGUEST_MASTER_IDT_OFF(%eax);				\
 	/* Switch to master's stack. */					\
-	movl	master_stackptr, %esp;					\
+	movl	LGUEST_MASTER_STKP_OFF(%eax), %esp;			\
 	/* Switch to master's TSS */					\
 	movl	$(GDT_ENTRY_TSS*8), %eax;				\
 	ltr	%ax;							\
-	/* Set this to NULL as debugging aid */				\
-	movl	$0, currentdom;						\
 	/* Restore host regs */						\
 	popl	%ebx;							\
 	popl	%ecx;							\
diff -r 7e3cf18ea7a6 -r 62fdd3c03dac drivers/lguest/lguest.h
--- a/drivers/lguest/lguest.h	Thu Jan 11 19:57:19 2007 -0500
+++ b/drivers/lguest/lguest.h	Thu Jan 18 12:32:25 2007 -0500
@@ -18,7 +18,14 @@
 #define LGUEST_IDT_OFF		(LGUEST_GDTABLE_OFF + LGUEST_GDTABLE_SIZE)
 #define LGUEST_IDTABLE_SIZE	(8 * IDT_ENTRIES)
 #define LGUEST_IDTABLE_OFF	(LGUEST_IDT_OFF + 8)
-#define LGUEST_REGS_OFF		(LGUEST_IDTABLE_OFF + LGUEST_IDTABLE_SIZE)
+#define LGUEST_MASTER_OFF	(LGUEST_IDTABLE_OFF + LGUEST_IDTABLE_SIZE)
+#define LGUEST_MASTER_GDT_OFF	LGUEST_MASTER_OFF
+#define LGUEST_MASTER_IDT_OFF	(LGUEST_MASTER_OFF + 8)
+#define LGUEST_MASTER_PGDIR_OFF	(LGUEST_MASTER_IDT_OFF + 8)
+#define LGUEST_MASTER_STKP_OFF	(LGUEST_MASTER_PGDIR_OFF + 4)
+#define LGUEST_MASTER_CR4_OFF	(LGUEST_MASTER_STKP_OFF + 4)
+#define LGUEST_MASTER_SIZE	(8+8+4+4+4)
+#define LGUEST_REGS_OFF		(LGUEST_MASTER_OFF + LGUEST_MASTER_SIZE)	
 #define LGUEST_TRAPNUM_OFF	(LGUEST_REGS_OFF + 12*4)
 #define LGUEST_ERRCODE_OFF	(LGUEST_REGS_OFF + 13*4)
 
@@ -214,6 +221,15 @@ struct x86_tss
 
 int fixup_gdt_table(struct desc_struct *gdt, unsigned int num, struct x86_tss *tss);
 
+struct lguest_master
+{
+	struct Xgt_desc_struct	gdt;
+	struct Xgt_desc_struct	idt;
+	unsigned long		pgdir;
+	unsigned long		stackptr;
+	unsigned long		cr4;
+};
+
 struct lguest_guest
 {
 	/* Task struct. */
@@ -227,6 +243,9 @@ struct lguest_guest
 	struct Xgt_desc_struct idt;
 	struct desc_struct idt_table[IDT_ENTRIES];
 
+	/* Host state we store while the guest runs. */
+	struct lguest_master master;
+
 	/* This is the stack on which we push our regs. */
 	struct lguest_regs regs;
 };
