Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-f…
Browse files Browse the repository at this point in the history
…or-linus

* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: (27 commits)
  lguest: use __PAGE_KERNEL instead of _PAGE_KERNEL
  lguest: Use explicit includes rateher than indirect
  lguest: get rid of lg variable assignments
  lguest: change gpte_addr header
  lguest: move changed bitmap to lg_cpu
  lguest: move last_pages to lg_cpu
  lguest: change last_guest to last_cpu
  lguest: change spte_addr header
  lguest: per-vcpu lguest pgdir management
  lguest: make pending notifications per-vcpu
  lguest: makes special fields be per-vcpu
  lguest: per-vcpu lguest task management
  lguest: replace lguest_arch with lg_cpu_arch.
  lguest: make registers per-vcpu
  lguest: make emulate_insn receive a vcpu struct.
  lguest: map_switcher_in_guest() per-vcpu
  lguest: per-vcpu interrupt processing.
  lguest: per-vcpu lguest timers
  lguest: make hypercalls use the vcpu struct
  lguest: make write() operation smp aware
  ...

Manual conflict resolved (maybe even correctly, who knows) in
drivers/lguest/x86/core.c
  • Loading branch information
torvalds committed Jan 30, 2008
2 parents 44c3b59 + 84f12e3 commit d145c72
Show file tree
Hide file tree
Showing 13 changed files with 571 additions and 455 deletions.
49 changes: 43 additions & 6 deletions Documentation/lguest/lguest.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ static void *guest_base;
/* The maximum guest physical address allowed, and maximum possible. */
static unsigned long guest_limit, guest_max;

/* a per-cpu variable indicating whose vcpu is currently running */
static unsigned int __thread cpu_id;

/* This is our list of devices. */
struct device_list
{
Expand Down Expand Up @@ -153,6 +156,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()
Expand Down Expand Up @@ -554,7 +560,7 @@ static void wake_parent(int pipefd, int lguest_fd)
else
FD_CLR(-fd - 1, &devices.infds);
} else /* Send LHREQ_BREAK command. */
write(lguest_fd, args, sizeof(args));
pwrite(lguest_fd, args, sizeof(args), cpu_id);
}
}

Expand Down Expand Up @@ -1489,7 +1495,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. */
Expand All @@ -1499,7 +1507,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. */
Expand All @@ -1511,7 +1533,8 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
int readval;

/* We read from the /dev/lguest device to run the Guest. */
readval = read(lguest_fd, &notify_addr, sizeof(notify_addr));
readval = pread(lguest_fd, &notify_addr,
sizeof(notify_addr), cpu_id);

/* One unsigned long means the Guest did HCALL_NOTIFY */
if (readval == sizeof(notify_addr)) {
Expand All @@ -1521,16 +1544,23 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
/* ENOENT means the Guest died. Reading tells us why. */
} else if (errno == ENOENT) {
char reason[1024] = { 0 };
read(lguest_fd, reason, sizeof(reason)-1);
pread(lguest_fd, reason, sizeof(reason)-1, cpu_id);
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)
err(1, "Running guest failed");

/* Only service input on thread for CPU 0. */
if (cpu_id != 0)
continue;

/* Service input, then unset the BREAK to release the Waker. */
handle_input(lguest_fd);
if (write(lguest_fd, args, sizeof(args)) < 0)
if (pwrite(lguest_fd, args, sizeof(args), cpu_id) < 0)
err(1, "Resetting break");
}
}
Expand Down Expand Up @@ -1571,6 +1601,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
Expand All @@ -1582,6 +1618,7 @@ int main(int argc, char *argv[])
devices.lastdev = &devices.dev;
devices.next_irq = 1;

cpu_id = 0;
/* We need to know how much memory so we can set up the device
* descriptor and memory pages for the devices as we parse the command
* line. So we quickly look through the arguments to find the amount
Expand Down
11 changes: 9 additions & 2 deletions arch/x86/lguest/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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!
*
Expand Down Expand Up @@ -813,7 +814,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);
}

/*
Expand All @@ -823,7 +824,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;
}
Expand Down Expand Up @@ -927,6 +928,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. */
Expand Down Expand Up @@ -1060,6 +1066,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();
Expand Down
2 changes: 1 addition & 1 deletion drivers/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ obj-$(CONFIG_ISDN) += isdn/
obj-$(CONFIG_EDAC) += edac/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_LGUEST_GUEST) += lguest/
obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/
obj-$(CONFIG_MMC) += mmc/
Expand Down
46 changes: 24 additions & 22 deletions drivers/lguest/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,57 +151,57 @@ int lguest_address_ok(const struct lguest *lg,
/* This routine copies memory from the Guest. Here we can see how useful the
* kill_lguest() routine we met in the Launcher can be: we return a random
* value (all zeroes) instead of needing to return an error. */
void __lgread(struct lguest *lg, void *b, unsigned long addr, unsigned bytes)
void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes)
{
if (!lguest_address_ok(lg, addr, bytes)
|| copy_from_user(b, lg->mem_base + addr, bytes) != 0) {
if (!lguest_address_ok(cpu->lg, addr, bytes)
|| copy_from_user(b, cpu->lg->mem_base + addr, bytes) != 0) {
/* copy_from_user should do this, but as we rely on it... */
memset(b, 0, bytes);
kill_guest(lg, "bad read address %#lx len %u", addr, bytes);
kill_guest(cpu, "bad read address %#lx len %u", addr, bytes);
}
}

/* This is the write (copy into guest) version. */
void __lgwrite(struct lguest *lg, unsigned long addr, const void *b,
void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b,
unsigned bytes)
{
if (!lguest_address_ok(lg, addr, bytes)
|| copy_to_user(lg->mem_base + addr, b, bytes) != 0)
kill_guest(lg, "bad write address %#lx len %u", addr, bytes);
if (!lguest_address_ok(cpu->lg, addr, bytes)
|| copy_to_user(cpu->lg->mem_base + addr, b, bytes) != 0)
kill_guest(cpu, "bad write address %#lx len %u", addr, bytes);
}
/*:*/

/*H:030 Let's jump straight to the the main loop which runs the Guest.
* Remember, this is called by the Launcher reading /dev/lguest, and we keep
* going around and around until something interesting happens. */
int run_guest(struct lguest *lg, unsigned long __user *user)
int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
{
/* We stop running once the Guest is dead. */
while (!lg->dead) {
while (!cpu->lg->dead) {
/* First we run any hypercalls the Guest wants done. */
if (lg->hcall)
do_hypercalls(lg);
if (cpu->hcall)
do_hypercalls(cpu);

/* It's possible the Guest did a NOTIFY hypercall to the
* Launcher, in which case we return from the read() now. */
if (lg->pending_notify) {
if (put_user(lg->pending_notify, user))
if (cpu->pending_notify) {
if (put_user(cpu->pending_notify, user))
return -EFAULT;
return sizeof(lg->pending_notify);
return sizeof(cpu->pending_notify);
}

/* Check for signals */
if (signal_pending(current))
return -ERESTARTSYS;

/* If Waker set break_out, return to Launcher. */
if (lg->break_out)
if (cpu->break_out)
return -EAGAIN;

/* Check if there are any interrupts which can be delivered
* now: if so, this sets up the hander to be executed when we
* next run the Guest. */
maybe_do_interrupt(lg);
maybe_do_interrupt(cpu);

/* All long-lived kernel loops need to check with this horrible
* thing called the freezer. If the Host is trying to suspend,
Expand All @@ -210,12 +210,12 @@ int run_guest(struct lguest *lg, unsigned long __user *user)

/* Just make absolutely sure the Guest is still alive. One of
* those hypercalls could have been fatal, for example. */
if (lg->dead)
if (cpu->lg->dead)
break;

/* If the Guest asked to be stopped, we sleep. The Guest's
* clock timer or LHCALL_BREAK from the Waker will wake us. */
if (lg->halted) {
if (cpu->halted) {
set_current_state(TASK_INTERRUPTIBLE);
schedule();
continue;
Expand All @@ -226,15 +226,17 @@ int run_guest(struct lguest *lg, unsigned long __user *user)
local_irq_disable();

/* Actually run the Guest until something happens. */
lguest_arch_run_guest(lg);
lguest_arch_run_guest(cpu);

/* Now we're ready to be interrupted or moved to other CPUs */
local_irq_enable();

/* Now we deal with whatever happened to the Guest. */
lguest_arch_handle_trap(lg);
lguest_arch_handle_trap(cpu);
}

if (cpu->lg->dead == ERR_PTR(-ERESTART))
return -ERESTART;
/* The Guest is dead => "No such file or directory" */
return -ENOENT;
}
Expand All @@ -253,7 +255,7 @@ static int __init init(void)

/* Lguest can't run under Xen, VMI or itself. It does Tricky Stuff. */
if (paravirt_enabled()) {
printk("lguest is afraid of %s\n", pv_info.name);
printk("lguest is afraid of being a guest\n");
return -EPERM;
}

Expand Down
Loading

0 comments on commit d145c72

Please sign in to comment.