aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/lguest/lguest.c32
-rw-r--r--arch/x86/lguest/boot.c11
-rw-r--r--drivers/lguest/core.c2
-rw-r--r--drivers/lguest/hypercalls.c6
-rw-r--r--include/asm-x86/lguest_hcall.h6
5 files changed, 50 insertions, 7 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 9b0e322118b5..86cac3e622ab 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -153,6 +153,9 @@ struct virtqueue
153 void (*handle_output)(int fd, struct virtqueue *me); 153 void (*handle_output)(int fd, struct virtqueue *me);
154}; 154};
155 155
156/* Remember the arguments to the program so we can "reboot" */
157static char **main_args;
158
156/* Since guest is UP and we don't run at the same time, we don't need barriers. 159/* Since guest is UP and we don't run at the same time, we don't need barriers.
157 * But I include them in the code in case others copy it. */ 160 * But I include them in the code in case others copy it. */
158#define wmb() 161#define wmb()
@@ -1489,7 +1492,9 @@ static void setup_block_file(const char *filename)
1489 1492
1490 /* Create stack for thread and run it */ 1493 /* Create stack for thread and run it */
1491 stack = malloc(32768); 1494 stack = malloc(32768);
1492 if (clone(io_thread, stack + 32768, CLONE_VM, dev) == -1) 1495 /* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from
1496 * becoming a zombie. */
1497 if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1)
1493 err(1, "Creating clone"); 1498 err(1, "Creating clone");
1494 1499
1495 /* We don't need to keep the I/O thread's end of the pipes open. */ 1500 /* We don't need to keep the I/O thread's end of the pipes open. */
@@ -1499,7 +1504,21 @@ static void setup_block_file(const char *filename)
1499 verbose("device %u: virtblock %llu sectors\n", 1504 verbose("device %u: virtblock %llu sectors\n",
1500 devices.device_num, cap); 1505 devices.device_num, cap);
1501} 1506}
1502/* That's the end of device setup. */ 1507/* That's the end of device setup. :*/
1508
1509/* Reboot */
1510static void __attribute__((noreturn)) restart_guest(void)
1511{
1512 unsigned int i;
1513
1514 /* Closing pipes causes the waker thread and io_threads to die, and
1515 * closing /dev/lguest cleans up the Guest. Since we don't track all
1516 * open fds, we simply close everything beyond stderr. */
1517 for (i = 3; i < FD_SETSIZE; i++)
1518 close(i);
1519 execv(main_args[0], main_args);
1520 err(1, "Could not exec %s", main_args[0]);
1521}
1503 1522
1504/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves 1523/*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves
1505 * its input and output, and finally, lays it to rest. */ 1524 * its input and output, and finally, lays it to rest. */
@@ -1523,6 +1542,9 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
1523 char reason[1024] = { 0 }; 1542 char reason[1024] = { 0 };
1524 read(lguest_fd, reason, sizeof(reason)-1); 1543 read(lguest_fd, reason, sizeof(reason)-1);
1525 errx(1, "%s", reason); 1544 errx(1, "%s", reason);
1545 /* ERESTART means that we need to reboot the guest */
1546 } else if (errno == ERESTART) {
1547 restart_guest();
1526 /* EAGAIN means the Waker wanted us to look at some input. 1548 /* EAGAIN means the Waker wanted us to look at some input.
1527 * Anything else means a bug or incompatible change. */ 1549 * Anything else means a bug or incompatible change. */
1528 } else if (errno != EAGAIN) 1550 } else if (errno != EAGAIN)
@@ -1571,6 +1593,12 @@ int main(int argc, char *argv[])
1571 /* If they specify an initrd file to load. */ 1593 /* If they specify an initrd file to load. */
1572 const char *initrd_name = NULL; 1594 const char *initrd_name = NULL;
1573 1595
1596 /* Save the args: we "reboot" by execing ourselves again. */
1597 main_args = argv;
1598 /* We don't "wait" for the children, so prevent them from becoming
1599 * zombies. */
1600 signal(SIGCHLD, SIG_IGN);
1601
1574 /* First we initialize the device list. Since console and network 1602 /* First we initialize the device list. Since console and network
1575 * device receive input from a file descriptor, we keep an fdset 1603 * device receive input from a file descriptor, we keep an fdset
1576 * (infds) and the maximum fd number (max_infd) with the head of the 1604 * (infds) and the maximum fd number (max_infd) with the head of the
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 92c56117eae5..d6b18e2e5431 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -67,6 +67,7 @@
67#include <asm/mce.h> 67#include <asm/mce.h>
68#include <asm/io.h> 68#include <asm/io.h>
69#include <asm/i387.h> 69#include <asm/i387.h>
70#include <asm/reboot.h> /* for struct machine_ops */
70 71
71/*G:010 Welcome to the Guest! 72/*G:010 Welcome to the Guest!
72 * 73 *
@@ -812,7 +813,7 @@ static void lguest_safe_halt(void)
812 * rather than virtual addresses, so we use __pa() here. */ 813 * rather than virtual addresses, so we use __pa() here. */
813static void lguest_power_off(void) 814static void lguest_power_off(void)
814{ 815{
815 hcall(LHCALL_CRASH, __pa("Power down"), 0, 0); 816 hcall(LHCALL_SHUTDOWN, __pa("Power down"), LGUEST_SHUTDOWN_POWEROFF, 0);
816} 817}
817 818
818/* 819/*
@@ -822,7 +823,7 @@ static void lguest_power_off(void)
822 */ 823 */
823static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) 824static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p)
824{ 825{
825 hcall(LHCALL_CRASH, __pa(p), 0, 0); 826 hcall(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF, 0);
826 /* The hcall won't return, but to keep gcc happy, we're "done". */ 827 /* The hcall won't return, but to keep gcc happy, we're "done". */
827 return NOTIFY_DONE; 828 return NOTIFY_DONE;
828} 829}
@@ -926,6 +927,11 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
926 return insn_len; 927 return insn_len;
927} 928}
928 929
930static void lguest_restart(char *reason)
931{
932 hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0);
933}
934
929/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops 935/*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops
930 * structures in the kernel provide points for (almost) every routine we have 936 * structures in the kernel provide points for (almost) every routine we have
931 * to override to avoid privileged instructions. */ 937 * to override to avoid privileged instructions. */
@@ -1059,6 +1065,7 @@ __init void lguest_init(void)
1059 * the Guest routine to power off. */ 1065 * the Guest routine to power off. */
1060 pm_power_off = lguest_power_off; 1066 pm_power_off = lguest_power_off;
1061 1067
1068 machine_ops.restart = lguest_restart;
1062 /* Now we're set up, call start_kernel() in init/main.c and we proceed 1069 /* Now we're set up, call start_kernel() in init/main.c and we proceed
1063 * to boot as normal. It never returns. */ 1070 * to boot as normal. It never returns. */
1064 start_kernel(); 1071 start_kernel();
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index f10abc8d7635..c1069bceba11 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -235,6 +235,8 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
235 lguest_arch_handle_trap(lg); 235 lguest_arch_handle_trap(lg);
236 } 236 }
237 237
238 if (lg->dead == ERR_PTR(-ERESTART))
239 return -ERESTART;
238 /* The Guest is dead => "No such file or directory" */ 240 /* The Guest is dead => "No such file or directory" */
239 return -ENOENT; 241 return -ENOENT;
240} 242}
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index b478affe8f91..05fad6fa8049 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -41,8 +41,8 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
41 * do that. */ 41 * do that. */
42 kill_guest(lg, "already have lguest_data"); 42 kill_guest(lg, "already have lguest_data");
43 break; 43 break;
44 case LHCALL_CRASH: { 44 case LHCALL_SHUTDOWN: {
45 /* Crash is such a trivial hypercall that we do it in four 45 /* Shutdown is such a trivial hypercall that we do it in four
46 * lines right here. */ 46 * lines right here. */
47 char msg[128]; 47 char msg[128];
48 /* If the lgread fails, it will call kill_guest() itself; the 48 /* If the lgread fails, it will call kill_guest() itself; the
@@ -50,6 +50,8 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
50 __lgread(lg, msg, args->arg1, sizeof(msg)); 50 __lgread(lg, msg, args->arg1, sizeof(msg));
51 msg[sizeof(msg)-1] = '\0'; 51 msg[sizeof(msg)-1] = '\0';
52 kill_guest(lg, "CRASH: %s", msg); 52 kill_guest(lg, "CRASH: %s", msg);
53 if (args->arg2 == LGUEST_SHUTDOWN_RESTART)
54 lg->dead = ERR_PTR(-ERESTART);
53 break; 55 break;
54 } 56 }
55 case LHCALL_FLUSH_TLB: 57 case LHCALL_FLUSH_TLB:
diff --git a/include/asm-x86/lguest_hcall.h b/include/asm-x86/lguest_hcall.h
index 2091779e91fb..758b9a5d4539 100644
--- a/include/asm-x86/lguest_hcall.h
+++ b/include/asm-x86/lguest_hcall.h
@@ -4,7 +4,7 @@
4 4
5#define LHCALL_FLUSH_ASYNC 0 5#define LHCALL_FLUSH_ASYNC 0
6#define LHCALL_LGUEST_INIT 1 6#define LHCALL_LGUEST_INIT 1
7#define LHCALL_CRASH 2 7#define LHCALL_SHUTDOWN 2
8#define LHCALL_LOAD_GDT 3 8#define LHCALL_LOAD_GDT 3
9#define LHCALL_NEW_PGTABLE 4 9#define LHCALL_NEW_PGTABLE 4
10#define LHCALL_FLUSH_TLB 5 10#define LHCALL_FLUSH_TLB 5
@@ -20,6 +20,10 @@
20 20
21#define LGUEST_TRAP_ENTRY 0x1F 21#define LGUEST_TRAP_ENTRY 0x1F
22 22
23/* Argument number 3 to LHCALL_LGUEST_SHUTDOWN */
24#define LGUEST_SHUTDOWN_POWEROFF 1
25#define LGUEST_SHUTDOWN_RESTART 2
26
23#ifndef __ASSEMBLY__ 27#ifndef __ASSEMBLY__
24#include <asm/hw_irq.h> 28#include <asm/hw_irq.h>
25 29