[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