[Lguest] lca tutorial

Hamish Coleman hamish at zot.org
Thu Jan 31 12:40:17 EST 2008


I never got the S-lshutdown to work properly  :-(


diff -ur orig/linux-source-2.6.23/Documentation/lguest/lguest.c linux-source-2.6.23/Documentation/lguest/lguest.c
--- orig/linux-source-2.6.23/Documentation/lguest/lguest.c	2007-10-10 06:31:38.000000000 +1000
+++ linux-source-2.6.23/Documentation/lguest/lguest.c	2008-01-31 12:06:40.310997465 +1100
@@ -696,8 +696,23 @@
 	int count;
 	/* When did they start? */
 	struct timeval start;
+
+	/* was the last char a ctrl-A ? */
+	int ctrla;
 };
 
+/* The console code to kill the guest */
+static void console_exit(int fd) {
+	u32 args[] = { LHREQ_BREAK, 0 };
+	/* Close the fd so Waker will know it has to
+	 * exit. */
+	close(waker_fd);
+	/* Just in case waker is blocked in BREAK, send
+	 * unbreak now. */
+	write(fd, args, sizeof(args));
+	exit(2);
+}
+
 /* This is the routine which handles console input (ie. stdin). */
 static bool handle_console_input(int fd, struct device *dev)
 {
@@ -734,32 +749,51 @@
 		trigger_irq(fd, irq);
 	}
 
-	/* Three ^C within one second?  Exit.
-	 *
-	 * This is such a hack, but works surprisingly well.  Each ^C has to be
-	 * in a buffer by itself, so they can't be too fast.  But we check that
-	 * we get three within about a second, so they can't be too slow. */
-	if (len == 1 && ((char *)iov[0].iov_base)[0] == 3) {
-		if (!abort->count++)
-			gettimeofday(&abort->start, NULL);
-		else if (abort->count == 3) {
-			struct timeval now;
-			gettimeofday(&now, NULL);
-			if (now.tv_sec <= abort->start.tv_sec+1) {
-				u32 args[] = { LHREQ_BREAK, 0 };
-				/* Close the fd so Waker will know it has to
-				 * exit. */
-				close(waker_fd);
-				/* Just in case waker is blocked in BREAK, send
-				 * unbreak now. */
-				write(fd, args, sizeof(args));
-				exit(2);
+	/* If it is a one char buffer, consider it for ctrl-char processing */
+	/*
+	 * This is such a hack, but works surprisingly well.  Each char
+	 * has to be in a buffer by itself, so they can't be
+	 * too fast.  But we check that * we get three within
+	 * about a second, so they can't be too slow. */
+	if (len == 1) {
+		switch ( ((char *)iov[0].iov_base)[0] ) {
+
+		/* Three ^C within one second?  Exit.  */
+		case 3:
+			if (!abort->count++) 
+				gettimeofday(&abort->start, NULL);
+			else if (abort->count == 3) {
+				struct timeval now;
+				gettimeofday(&now, NULL);
+				if (now.tv_sec <= abort->start.tv_sec+1) {
+					console_exit(fd);
+				}
+				abort->count = 0;
 			}
+			break;
+
+		/* ctrl-A: console command prefix */
+		case 1:
+			abort->ctrla=1;
+			break;
+		/* ctrl-K: Kill */
+		case 11:
+			if (abort->ctrla)
+				console_exit(fd);
+			break;
+		/* ctrl-R: Reboot */
+		case 19:
+			
+		default:
+			/* Any other key resets the abort counter. */
 			abort->count = 0;
+			abort->ctrla=0;
 		}
-	} else
+	} else {
 		/* Any other key resets the abort counter. */
 		abort->count = 0;
+		abort->ctrla=0;
+	}
 
 	/* Now, if we didn't read anything, put the input terminal back and
 	 * return failure (meaning, don't call us again). */
@@ -1342,8 +1376,18 @@
 		/* ENOENT means the Guest died.  Reading tells us why. */
 		} else if (errno == ENOENT) {
 			char reason[1024] = { 0 };
-			read(lguest_fd, reason, sizeof(reason)-1);
-			errx(1, "%s", reason);
+			int read_size;
+			int exit_code = 1;
+
+			read_size = read(lguest_fd, reason, sizeof(reason)-1);
+
+			/* If the reason is empty, then this is a clean
+			 * shutdown
+			 */
+			if (!read_size) {
+				exit_code=0;
+			}
+			errx(exit_code, "%s", reason);
 		/* EAGAIN means the waker wanted us to look at some input.
 		 * Anything else means a bug or incompatible change. */
 		} else if (errno != EAGAIN)
diff -ur orig/linux-source-2.6.23/drivers/lguest/hypercalls.c linux-source-2.6.23/drivers/lguest/hypercalls.c
--- orig/linux-source-2.6.23/drivers/lguest/hypercalls.c	2007-10-10 06:31:38.000000000 +1000
+++ linux-source-2.6.23/drivers/lguest/hypercalls.c	2008-01-31 12:24:54.661795468 +1100
@@ -29,7 +29,7 @@
 #include "lg.h"
 
 /*H:120 This is the core hypercall routine: where the Guest gets what it
- * wants.  Or gets killed.  Or, in the case of LHCALL_CRASH, both.
+ * wants.  Or gets killed.  Or, in the case of LHCALL_STOP, both.
  *
  * Remember from the Guest: %eax == which call to make, and the arguments are
  * packed into %edx, %ebx and %ecx if needed. */
@@ -45,7 +45,7 @@
 		 * do that. */
 		kill_guest(lg, "already have lguest_data");
 		break;
-	case LHCALL_CRASH: {
+	case LHCALL_STOP: {
 		/* Crash is such a trivial hypercall that we do it in four
 		 * lines right here. */
 		char msg[128];
@@ -53,7 +53,13 @@
 		 * kill_guest() with the message will be ignored. */
 		lgread(lg, msg, regs->edx, sizeof(msg));
 		msg[sizeof(msg)-1] = '\0';
-		kill_guest(lg, "CRASH: %s", msg);
+
+		if (regs->ebx== LHCALL_STOP_SHUTDOWN) {
+			/* tell the launcher that we actually shutdown */
+			lg->dead = 0;
+		}
+
+		kill_guest(lg, "STOP(%i): %s", regs->ebx, msg);
 		break;
 	}
 	case LHCALL_FLUSH_TLB:
diff -ur orig/linux-source-2.6.23/drivers/lguest/lguest.c linux-source-2.6.23/drivers/lguest/lguest.c
--- orig/linux-source-2.6.23/drivers/lguest/lguest.c	2007-10-10 06:31:38.000000000 +1000
+++ linux-source-2.6.23/drivers/lguest/lguest.c	2008-01-31 12:16:55.622746489 +1100
@@ -65,6 +65,8 @@
 #include <asm/e820.h>
 #include <asm/mce.h>
 #include <asm/io.h>
+#include <asm/reboot.h>
+
 
 /*G:010 Welcome to the Guest!
  *
@@ -857,7 +859,7 @@
 	hcall(LHCALL_HALT, 0, 0, 0);
 }
 
-/* Perhaps CRASH isn't the best name for this hypercall, but we use it to get a
+/* HC FIXME - message now incorrect: Perhaps CRASH isn't the best name for this hypercall, but we use it to get a
  * message out when we're crashing as well as elegant termination like powering
  * off.
  *
@@ -865,7 +867,7 @@
  * rather than virtual addresses, so we use __pa() here. */
 static void lguest_power_off(void)
 {
-	hcall(LHCALL_CRASH, __pa("Power down"), 0, 0);
+	hcall(LHCALL_STOP, __pa("Power down"), LHCALL_STOP_SHUTDOWN, 0);
 }
 
 /*
@@ -875,7 +877,7 @@
  */
 static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p)
 {
-	hcall(LHCALL_CRASH, __pa(p), 0, 0);
+	hcall(LHCALL_STOP, __pa(p), LHCALL_STOP_CRASH, 0);
 	/* The hcall won't return, but to keep gcc happy, we're "done". */
 	return NOTIFY_DONE;
 }
@@ -957,6 +959,19 @@
 	return insn_len;
 }
 
+/* HC
+ */
+static void lguest_reboot(char *msg) {
+	/* Without checking the users of machine_ops.restart, I guess
+	  that they are not setting a message */
+	char *buf = "";
+	if (!msg)
+		msg = buf;
+
+	hcall(LHCALL_STOP,__pa(msg),LHCALL_STOP_REBOOT,0);
+	/* TODO - crash? */
+}
+
 /*G:030 Once we get to lguest_init(), we know we're a Guest.  The paravirt_ops
  * structure in the kernel provides a single point for (almost) every routine
  * we have to override to avoid privileged instructions. */
@@ -1025,6 +1040,11 @@
 	/* Now is a good time to look at the implementations of these functions
 	 * before returning to the rest of lguest_init(). */
 
+	/* overwrite the standard reboot hook with our own */
+	machine_ops.restart = lguest_reboot;
+	/* some user-spaces dont use power management to halt */
+	machine_ops.halt = lguest_power_off;
+
 	/*G:070 Now we've seen all the paravirt_ops, we return to
 	 * lguest_init() where the rest of the fairly chaotic boot setup
 	 * occurs.
@@ -1092,6 +1112,7 @@
 
 	/* Now we're set up, call start_kernel() in init/main.c and we proceed
 	 * to boot as normal.  It never returns. */
+
 	start_kernel();
 }
 /*


-- 
Use Linux!                                                  hamish at zot.org
*********************************** O- ***********************************
``Life is like a grapefruit ... it's sort of orangey-yellow and dimpled on
the outside, wet and squidgy in the middle.  It's got pips inside too. Oh,
and some people have half a one for breakfast.'' -- Ford Prefect

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.ozlabs.org/pipermail/lguest/attachments/20080131/a63f04c6/attachment.pgp>


More information about the Lguest mailing list