diff -r 47005973abff arch/i386/Kconfig
--- a/arch/i386/Kconfig	Thu Feb 08 10:20:05 2007 -0500
+++ b/arch/i386/Kconfig	Thu Feb 08 10:41:49 2007 -0500
@@ -232,6 +232,7 @@ config LGUEST
 	depends on X86 && PARAVIRT && EXPERIMENTAL && !X86_PAE
 	select LGUEST_GUEST
 	select HVC_DRIVER
+	select SYS_HYPERVISOR if SYSFS
 	---help---
 	  This is a very simple module which allows you to run
 	  multiple instances of the same Linux kernel, using the
diff -r 47005973abff drivers/lguest/Makefile
--- a/drivers/lguest/Makefile	Thu Feb 08 10:20:05 2007 -0500
+++ b/drivers/lguest/Makefile	Thu Feb 08 10:41:49 2007 -0500
@@ -1,6 +1,10 @@ obj-$(CONFIG_LGUEST)	+= lg.o
 obj-$(CONFIG_LGUEST)	+= lg.o
 
 lg-objs := core.o device.o hypercalls.o page_tables.o io.o
+
+ifeq ($(CONFIG_SYSFS),y)
+lg-objs += sysfs.o
+endif
 
 # We use top 4MB for guest traps page then hypervisor. */
 HYPE_ADDR := (0xFFC00000+4096)
diff -r 47005973abff drivers/lguest/core.c
--- a/drivers/lguest/core.c	Thu Feb 08 10:20:05 2007 -0500
+++ b/drivers/lguest/core.c	Thu Feb 08 10:41:49 2007 -0500
@@ -685,39 +685,53 @@ static void adjust_pge(void *on)
  
 static int __init init(void)
 {
-	int err;
+	int err = -EPERM;
 
 	if (paravirt_enabled())
-		return -EPERM;
+		goto out;
 
 	err = map_hypervisor();
 	if (err)
-		return err;
+		goto out;
 
 	err = init_pagetables(hype_pages);
-	if (err) {
-		unmap_hypervisor();
-		return err;
-	}
+	if (err)
+		goto unmap_hypervisor;
+
 	lguest_io_init();
 
+	err = lguest_sysfs_init();
+	if (err)
+		goto free_pagetables;
+
 	err = lguest_device_init();
-	if (err) {
-		free_pagetables();
-		unmap_hypervisor();
-		return err;
-	}
+	if (err)
+		goto exit_sysfs;
+
 	if (cpu_has_pge) { /* We have a broader idea of "global". */
 		cpu_had_pge = 1;
 		on_each_cpu(adjust_pge, 0, 0, 1);
 		clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
 	}
-	return 0;
+
+out:
+	return err;
+
+exit_sysfs:
+	lguest_sysfs_exit();
+	
+free_pagetables:
+	free_pagetables();
+
+unmap_hypervisor:
+	unmap_hypervisor();
+	goto out;
 }
 
 static void __exit fini(void)
 {
 	lguest_device_remove();
+	lguest_sysfs_exit();
 	free_pagetables();
 	unmap_hypervisor();
 	if (cpu_had_pge) {
diff -r 47005973abff drivers/lguest/device.c
--- a/drivers/lguest/device.c	Thu Feb 08 10:20:05 2007 -0500
+++ b/drivers/lguest/device.c	Thu Feb 08 13:31:32 2007 -0500
@@ -158,6 +158,11 @@ static int initialize(struct file *file,
 		err = -ENOEXEC;
 		goto release_pgtable;
 	}
+
+	err = lguest_sysfs_setup(linfo);
+	if (err)
+		goto release_pgtable;
+
 	up(&lguest_lock);
 
 	linfo->tsk = current;
@@ -218,6 +223,7 @@ static int close(struct inode *inode, st
 	if (linfo->dead != (void *)1)
 		kfree(linfo->dead);
 	memset(linfo->guest, 0, sizeof(*linfo->guest));
+	lguest_sysfs_close(linfo);
 	memset(linfo, 0, sizeof(*linfo));
 	up(&lguest_lock);
 	return 0;
diff -r 47005973abff drivers/lguest/lguest.h
--- a/drivers/lguest/lguest.h	Thu Feb 08 10:20:05 2007 -0500
+++ b/drivers/lguest/lguest.h	Thu Feb 08 13:39:37 2007 -0500
@@ -97,6 +97,7 @@ struct lguest_guest_info
 	struct lguest_data __user *lguest_data;
 	struct task_struct *tsk;
 	struct mm_struct *mm; 	/* == tsk->mm, but that becomes NULL on exit */
+	struct kobject kobj;
 	u16 guestid;
 	u32 pfn_limit;
 	u32 page_offset;
@@ -250,5 +251,31 @@ struct lguest_guest
 	/* This is the stack on which we push our regs. */
 	struct lguest_regs regs;
 };
+
+#ifdef CONFIG_SYSFS
+int lguest_sysfs_setup(struct lguest_guest_info *linfo);
+void lguest_sysfs_close(struct lguest_guest_info *linfo);
+int __init lguest_sysfs_init(void);
+void __exit lguest_sysfs_exit(void);
+#else
+static inline int lguest_sysfs_setup(struct lguest_guest_info *linfo)
+{
+	return 0;
+}
+
+void lguest_sysfs_close(struct lguest_guest_info *linfo)
+{
+}
+
+static inline int lguest_sysfs_init(void)
+{
+	return 0;
+}
+
+static inline void lguest_sysfs_exit(void)
+{
+}
+#endif	/* CONFIG_SYSFS */
+
 #endif	/* __ASSEMBLY__ */
 #endif	/* _LGUEST_H */
diff -r 47005973abff drivers/lguest/sysfs.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/lguest/sysfs.c	Thu Feb 08 13:44:21 2007 -0500
@@ -0,0 +1,131 @@
+/*
+ * Guest attributes exported via sysfs: /sys/hypervisor/lguest/<guestid>
+ *
+ * Management apps can determine the host PID for each guest, and also
+ * use uevent to be notified when a guest is created or destroyed.
+ *
+ * Copyright (C) 2007 Red Hat, Inc., James Morris <jmorris@namei.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "lguest.h"
+
+struct lguest_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct lguest_guest_info *linfo, char *buf);
+	ssize_t (*store)(struct lguest_guest_info *linfo, const char *buf);
+};
+
+static ssize_t show_halted(struct lguest_guest_info *linfo, char *buffer)
+{
+	return sprintf(buffer, "%u\n", linfo->halted);
+}
+
+static ssize_t show_hostpid(struct lguest_guest_info *linfo, char *buffer)
+{
+	return sprintf(buffer, "%u\n", linfo->tsk->pid);
+}
+
+static struct lguest_attribute halted = {
+	.attr = { .name = "halted", .mode = S_IRUGO, .owner = THIS_MODULE },
+	.show = show_halted,
+};
+
+static struct lguest_attribute hostpid = {
+	.attr = { .name = "hostpid", .mode = S_IRUGO, .owner = THIS_MODULE },
+	.show = show_hostpid,
+};
+
+static struct lguest_attribute *lguest_attrs[] = {
+	&halted,
+	&hostpid,
+	NULL
+};
+
+#define to_lguest_attr(n) container_of(n, struct lguest_attribute, attr)
+#define to_lguest_info(n) container_of(n, struct lguest_guest_info, kobj)
+
+static ssize_t lguest_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	ssize_t ret = -EIO;
+	struct lguest_attribute *lattr = to_lguest_attr(attr);
+	struct lguest_guest_info *linfo = to_lguest_info(kobj);
+
+	if (lattr->show)
+		ret = lattr->show(linfo, buf);
+	return ret;
+}
+
+static struct sysfs_ops lguest_sysfs_ops = {
+	.show = lguest_attr_show,
+};
+
+static struct kobj_type lguest_ktype = {
+	.sysfs_ops = &lguest_sysfs_ops,
+};
+
+static decl_subsys(lguest, &lguest_ktype, NULL);
+
+static int lguest_sysfs_populate(struct lguest_guest_info *linfo)
+{
+	int err = 0;
+	struct lguest_attribute **p;
+	
+	for (p = lguest_attrs; *p; p++) {
+		err = sysfs_create_file(&linfo->kobj, &((*p)->attr));
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+int lguest_sysfs_setup(struct lguest_guest_info *linfo)
+{
+	int err;
+
+	err = kobject_set_name(&linfo->kobj, "%u", linfo->guestid);
+	if (err)
+		goto out;
+
+	kobj_set_kset_s(linfo, lguest_subsys);
+	kobject_init(&linfo->kobj);
+	
+	err = kobject_add(&linfo->kobj);
+	if (err)
+		goto out;
+	
+	err = lguest_sysfs_populate(linfo);
+	if (err)
+		goto kill_kobject;
+
+	kobject_uevent(&linfo->kobj, KOBJ_ADD);
+out:
+	return err;
+
+kill_kobject:
+	kobject_del(&linfo->kobj);
+	kobject_put(&linfo->kobj);
+	goto out;
+}
+
+void lguest_sysfs_close(struct lguest_guest_info *linfo)
+{
+	kobject_unregister(&linfo->kobj);
+}
+
+int __init lguest_sysfs_init(void)
+{
+	kset_set_kset_s(&lguest_subsys, hypervisor_subsys);
+	return subsystem_register(&lguest_subsys);
+}
+
+void __exit lguest_sysfs_exit(void)
+{
+	subsystem_unregister(&lguest_subsys);
+}
