Loading Documentation/lguest/lguest.c +30 −2 Original line number Diff line number Diff line Loading @@ -153,6 +153,9 @@ struct virtqueue void (*handle_output)(int fd, struct virtqueue *me); }; /* Remember the arguments to the program so we can "reboot" */ static char **main_args; /* Since guest is UP and we don't run at the same time, we don't need barriers. * But I include them in the code in case others copy it. */ #define wmb() Loading Loading @@ -1489,7 +1492,9 @@ static void setup_block_file(const char *filename) /* Create stack for thread and run it */ stack = malloc(32768); if (clone(io_thread, stack + 32768, CLONE_VM, dev) == -1) /* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from * becoming a zombie. */ if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1) err(1, "Creating clone"); /* We don't need to keep the I/O thread's end of the pipes open. */ Loading @@ -1499,7 +1504,21 @@ static void setup_block_file(const char *filename) verbose("device %u: virtblock %llu sectors\n", devices.device_num, cap); } /* That's the end of device setup. */ /* That's the end of device setup. :*/ /* Reboot */ static void __attribute__((noreturn)) restart_guest(void) { unsigned int i; /* Closing pipes causes the waker thread and io_threads to die, and * closing /dev/lguest cleans up the Guest. Since we don't track all * open fds, we simply close everything beyond stderr. */ for (i = 3; i < FD_SETSIZE; i++) close(i); execv(main_args[0], main_args); err(1, "Could not exec %s", main_args[0]); } /*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves * its input and output, and finally, lays it to rest. */ Loading @@ -1523,6 +1542,9 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd) char reason[1024] = { 0 }; read(lguest_fd, reason, sizeof(reason)-1); errx(1, "%s", reason); /* ERESTART means that we need to reboot the guest */ } else if (errno == ERESTART) { restart_guest(); /* EAGAIN means the Waker wanted us to look at some input. * Anything else means a bug or incompatible change. */ } else if (errno != EAGAIN) Loading Loading @@ -1571,6 +1593,12 @@ int main(int argc, char *argv[]) /* If they specify an initrd file to load. */ const char *initrd_name = NULL; /* Save the args: we "reboot" by execing ourselves again. */ main_args = argv; /* We don't "wait" for the children, so prevent them from becoming * zombies. */ signal(SIGCHLD, SIG_IGN); /* First we initialize the device list. Since console and network * device receive input from a file descriptor, we keep an fdset * (infds) and the maximum fd number (max_infd) with the head of the Loading arch/x86/lguest/boot.c +9 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #include <asm/mce.h> #include <asm/io.h> #include <asm/i387.h> #include <asm/reboot.h> /* for struct machine_ops */ /*G:010 Welcome to the Guest! * Loading Loading @@ -812,7 +813,7 @@ static void lguest_safe_halt(void) * 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_SHUTDOWN, __pa("Power down"), LGUEST_SHUTDOWN_POWEROFF, 0); } /* Loading @@ -822,7 +823,7 @@ static void lguest_power_off(void) */ static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) { hcall(LHCALL_CRASH, __pa(p), 0, 0); hcall(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF, 0); /* The hcall won't return, but to keep gcc happy, we're "done". */ return NOTIFY_DONE; } Loading Loading @@ -926,6 +927,11 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf, return insn_len; } static void lguest_restart(char *reason) { hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); } /*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops * structures in the kernel provide points for (almost) every routine we have * to override to avoid privileged instructions. */ Loading Loading @@ -1059,6 +1065,7 @@ __init void lguest_init(void) * the Guest routine to power off. */ pm_power_off = lguest_power_off; machine_ops.restart = lguest_restart; /* Now we're set up, call start_kernel() in init/main.c and we proceed * to boot as normal. It never returns. */ start_kernel(); Loading drivers/lguest/core.c +2 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,8 @@ int run_guest(struct lguest *lg, unsigned long __user *user) lguest_arch_handle_trap(lg); } if (lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; /* The Guest is dead => "No such file or directory" */ return -ENOENT; } Loading drivers/lguest/hypercalls.c +4 −2 Original line number Diff line number Diff line Loading @@ -41,8 +41,8 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args) * do that. */ kill_guest(lg, "already have lguest_data"); break; case LHCALL_CRASH: { /* Crash is such a trivial hypercall that we do it in four case LHCALL_SHUTDOWN: { /* Shutdown is such a trivial hypercall that we do it in four * lines right here. */ char msg[128]; /* If the lgread fails, it will call kill_guest() itself; the Loading @@ -50,6 +50,8 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args) __lgread(lg, msg, args->arg1, sizeof(msg)); msg[sizeof(msg)-1] = '\0'; kill_guest(lg, "CRASH: %s", msg); if (args->arg2 == LGUEST_SHUTDOWN_RESTART) lg->dead = ERR_PTR(-ERESTART); break; } case LHCALL_FLUSH_TLB: Loading include/asm-x86/lguest_hcall.h +5 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ #define LHCALL_FLUSH_ASYNC 0 #define LHCALL_LGUEST_INIT 1 #define LHCALL_CRASH 2 #define LHCALL_SHUTDOWN 2 #define LHCALL_LOAD_GDT 3 #define LHCALL_NEW_PGTABLE 4 #define LHCALL_FLUSH_TLB 5 Loading @@ -20,6 +20,10 @@ #define LGUEST_TRAP_ENTRY 0x1F /* Argument number 3 to LHCALL_LGUEST_SHUTDOWN */ #define LGUEST_SHUTDOWN_POWEROFF 1 #define LGUEST_SHUTDOWN_RESTART 2 #ifndef __ASSEMBLY__ #include <asm/hw_irq.h> Loading Loading
Documentation/lguest/lguest.c +30 −2 Original line number Diff line number Diff line Loading @@ -153,6 +153,9 @@ struct virtqueue void (*handle_output)(int fd, struct virtqueue *me); }; /* Remember the arguments to the program so we can "reboot" */ static char **main_args; /* Since guest is UP and we don't run at the same time, we don't need barriers. * But I include them in the code in case others copy it. */ #define wmb() Loading Loading @@ -1489,7 +1492,9 @@ static void setup_block_file(const char *filename) /* Create stack for thread and run it */ stack = malloc(32768); if (clone(io_thread, stack + 32768, CLONE_VM, dev) == -1) /* SIGCHLD - We dont "wait" for our cloned thread, so prevent it from * becoming a zombie. */ if (clone(io_thread, stack + 32768, CLONE_VM | SIGCHLD, dev) == -1) err(1, "Creating clone"); /* We don't need to keep the I/O thread's end of the pipes open. */ Loading @@ -1499,7 +1504,21 @@ static void setup_block_file(const char *filename) verbose("device %u: virtblock %llu sectors\n", devices.device_num, cap); } /* That's the end of device setup. */ /* That's the end of device setup. :*/ /* Reboot */ static void __attribute__((noreturn)) restart_guest(void) { unsigned int i; /* Closing pipes causes the waker thread and io_threads to die, and * closing /dev/lguest cleans up the Guest. Since we don't track all * open fds, we simply close everything beyond stderr. */ for (i = 3; i < FD_SETSIZE; i++) close(i); execv(main_args[0], main_args); err(1, "Could not exec %s", main_args[0]); } /*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves * its input and output, and finally, lays it to rest. */ Loading @@ -1523,6 +1542,9 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd) char reason[1024] = { 0 }; read(lguest_fd, reason, sizeof(reason)-1); errx(1, "%s", reason); /* ERESTART means that we need to reboot the guest */ } else if (errno == ERESTART) { restart_guest(); /* EAGAIN means the Waker wanted us to look at some input. * Anything else means a bug or incompatible change. */ } else if (errno != EAGAIN) Loading Loading @@ -1571,6 +1593,12 @@ int main(int argc, char *argv[]) /* If they specify an initrd file to load. */ const char *initrd_name = NULL; /* Save the args: we "reboot" by execing ourselves again. */ main_args = argv; /* We don't "wait" for the children, so prevent them from becoming * zombies. */ signal(SIGCHLD, SIG_IGN); /* First we initialize the device list. Since console and network * device receive input from a file descriptor, we keep an fdset * (infds) and the maximum fd number (max_infd) with the head of the Loading
arch/x86/lguest/boot.c +9 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #include <asm/mce.h> #include <asm/io.h> #include <asm/i387.h> #include <asm/reboot.h> /* for struct machine_ops */ /*G:010 Welcome to the Guest! * Loading Loading @@ -812,7 +813,7 @@ static void lguest_safe_halt(void) * 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_SHUTDOWN, __pa("Power down"), LGUEST_SHUTDOWN_POWEROFF, 0); } /* Loading @@ -822,7 +823,7 @@ static void lguest_power_off(void) */ static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p) { hcall(LHCALL_CRASH, __pa(p), 0, 0); hcall(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF, 0); /* The hcall won't return, but to keep gcc happy, we're "done". */ return NOTIFY_DONE; } Loading Loading @@ -926,6 +927,11 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf, return insn_len; } static void lguest_restart(char *reason) { hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0); } /*G:030 Once we get to lguest_init(), we know we're a Guest. The pv_ops * structures in the kernel provide points for (almost) every routine we have * to override to avoid privileged instructions. */ Loading Loading @@ -1059,6 +1065,7 @@ __init void lguest_init(void) * the Guest routine to power off. */ pm_power_off = lguest_power_off; machine_ops.restart = lguest_restart; /* Now we're set up, call start_kernel() in init/main.c and we proceed * to boot as normal. It never returns. */ start_kernel(); Loading
drivers/lguest/core.c +2 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,8 @@ int run_guest(struct lguest *lg, unsigned long __user *user) lguest_arch_handle_trap(lg); } if (lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; /* The Guest is dead => "No such file or directory" */ return -ENOENT; } Loading
drivers/lguest/hypercalls.c +4 −2 Original line number Diff line number Diff line Loading @@ -41,8 +41,8 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args) * do that. */ kill_guest(lg, "already have lguest_data"); break; case LHCALL_CRASH: { /* Crash is such a trivial hypercall that we do it in four case LHCALL_SHUTDOWN: { /* Shutdown is such a trivial hypercall that we do it in four * lines right here. */ char msg[128]; /* If the lgread fails, it will call kill_guest() itself; the Loading @@ -50,6 +50,8 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args) __lgread(lg, msg, args->arg1, sizeof(msg)); msg[sizeof(msg)-1] = '\0'; kill_guest(lg, "CRASH: %s", msg); if (args->arg2 == LGUEST_SHUTDOWN_RESTART) lg->dead = ERR_PTR(-ERESTART); break; } case LHCALL_FLUSH_TLB: Loading
include/asm-x86/lguest_hcall.h +5 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ #define LHCALL_FLUSH_ASYNC 0 #define LHCALL_LGUEST_INIT 1 #define LHCALL_CRASH 2 #define LHCALL_SHUTDOWN 2 #define LHCALL_LOAD_GDT 3 #define LHCALL_NEW_PGTABLE 4 #define LHCALL_FLUSH_TLB 5 Loading @@ -20,6 +20,10 @@ #define LGUEST_TRAP_ENTRY 0x1F /* Argument number 3 to LHCALL_LGUEST_SHUTDOWN */ #define LGUEST_SHUTDOWN_POWEROFF 1 #define LGUEST_SHUTDOWN_RESTART 2 #ifndef __ASSEMBLY__ #include <asm/hw_irq.h> Loading