lguest: tell Launcher where the Guest's lguest_data is

This allows the Launcher to peek into the irqs_disabled and blocked_interrupts
fields to do more analysis.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 Documentation/lguest/lguest.c       |   11 +++++++++++
 arch/x86/include/asm/lguest_hcall.h |    3 ---
 arch/x86/lguest/i386_head.S         |    1 -
 drivers/lguest/hypercalls.c         |    4 ++++
 include/linux/lguest.h              |   12 ++++++++----
 5 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -43,6 +43,7 @@
 #include <stddef.h>
 #include <signal.h>
 #include <stdarg.h>
+#include "linux/lguest.h"
 #include "linux/lguest_launcher.h"
 #include "linux/virtio_config.h"
 #include "linux/virtio_net.h"
@@ -87,6 +88,8 @@ static void *guest_base;
 static unsigned long guest_limit, guest_max;
 /* The /dev/lguest file descriptor. */
 static int lguest_fd;
+/* The lguest_data structure the Guest is using. */
+static struct lguest_data *lguest_data = NULL;
 
 /* a per-cpu variable indicating whose vcpu is currently running */
 static unsigned int __thread cpu_id;
@@ -1194,6 +1197,14 @@ static void handle_output(unsigned long 
 {
 	struct device *i;
 
+	/* Very first notify tells us where the lguest_data struct is
+	 * in the Guest. */
+	if (!lguest_data) {
+		lguest_data = check_pointer(addr, sizeof(*lguest_data));
+		verbose("lguest_data is %#lx => %p\n", addr, lguest_data);
+		return;
+	}
+
 	/* Check each device. */
 	for (i = devices.dev; i; i = i->next) {
 		struct virtqueue *vq;
diff --git a/arch/x86/include/asm/lguest_hcall.h b/arch/x86/include/asm/lguest_hcall.h
--- a/arch/x86/include/asm/lguest_hcall.h
+++ b/arch/x86/include/asm/lguest_hcall.h
@@ -44,9 +44,6 @@
  * definition of a gentleman: "someone who is only rude intentionally". */
 /*:*/
 
-/* Can't use our min() macro here: needs to be a constant */
-#define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
-
 #define LHCALL_RING_SIZE 64
 struct hcall_args {
 	/* These map directly onto eax, ebx, ecx, edx in struct lguest_regs */
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S
--- a/arch/x86/lguest/i386_head.S
+++ b/arch/x86/lguest/i386_head.S
@@ -1,5 +1,4 @@
 #include <linux/linkage.h>
-#include <linux/lguest.h>
 #include <asm/lguest_hcall.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -193,6 +193,10 @@ static void initialize(struct lg_cpu *cp
 	 * fault, but the old page might be (read-only) in the Guest
 	 * pagetable. */
 	guest_pagetable_clear_all(cpu);
+
+	/* Tell the Launcher where the lguest data is: this is always the
+	 * first (successful) return from pread. */
+	cpu->pending_notify = (void *)cpu->lg->lguest_data - cpu->lg->mem_base;
 }
 /*:*/
 
diff --git a/include/linux/lguest.h b/include/linux/lguest.h
--- a/include/linux/lguest.h
+++ b/include/linux/lguest.h
@@ -3,13 +3,16 @@
 #ifndef _LINUX_LGUEST_H
 #define _LINUX_LGUEST_H
 
-#ifndef __ASSEMBLY__
+#ifdef __KERNEL__
 #include <linux/time.h>
 #include <asm/irq.h>
 #include <asm/lguest_hcall.h>
 
 #define LG_CLOCK_MIN_DELTA	100UL
 #define LG_CLOCK_MAX_DELTA	ULONG_MAX
+#endif /* __KERNEL__ */
+
+#define LGUEST_IRQS	256
 
 /*G:032 The second method of communicating with the Host is to via "struct
  * lguest_data".  Once the Guest's initialization hypercall tells the Host where
@@ -20,8 +23,10 @@ struct lguest_data
 	 * changes interrupts so often that a hypercall is too slow. */
 	unsigned int irq_enabled;
 	/* Fine-grained interrupt disabling by the Guest */
-	DECLARE_BITMAP(blocked_interrupts, LGUEST_IRQS);
+	unsigned long blocked_interrupts[LGUEST_IRQS / sizeof(long) / 8];
 
+	/* Beyond this point, the Launcher doesn't need to know. */
+#ifdef __KERNEL__
 	/* The Host writes the virtual address of the last page fault here,
 	 * which saves the Guest a hypercall.  CR2 is the native register where
 	 * this address would normally be found. */
@@ -58,7 +63,6 @@ struct lguest_data
 	unsigned long kernel_address;
 	/* The vector to try to use for system calls (0x40 or 0x80). */
 	unsigned int syscall_vec;
+#endif /* __KERNEL__ */
 };
-extern struct lguest_data lguest_data;
-#endif /* __ASSEMBLY__ */
 #endif	/* _LINUX_LGUEST_H */
