Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec04b13f authored by Balaji Rao's avatar Balaji Rao Committed by Rusty Russell
Browse files

lguest: Reboot support



Reboot Implemented

(Prevent fd leak, fix style and fix documentation --RR)

Signed-off-by: default avatarBalaji Rao <balajirrao@gmail.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 5c55841d
Loading
Loading
Loading
Loading
+30 −2
Original line number Diff line number Diff line
@@ -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()
@@ -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. */
@@ -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. */
@@ -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)
@@ -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
+9 −2
Original line number Diff line number Diff line
@@ -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!
 *
@@ -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);
}

/*
@@ -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;
}
@@ -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. */
@@ -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();
+2 −0
Original line number Diff line number Diff line
@@ -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;
}
+4 −2
Original line number Diff line number Diff line
@@ -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
@@ -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:
+5 −1
Original line number Diff line number Diff line
@@ -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
@@ -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>