struct lg_cpu {
unsigned int id;
struct lguest *lg;
+ struct task_struct *tsk;
+ struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
/* At end of a page shared mapped over lguest_pages in guest. */
unsigned long regs_page;
/* Virtual clock device */
struct hrtimer hrt;
+ /* Do we need to stop what we're doing and return to userspace? */
+ int break_out;
+ wait_queue_head_t break_wq;
+ int halted;
+
/* Pending virtual interrupts */
DECLARE_BITMAP(irqs_pending, LGUEST_IRQS);
struct lguest
{
struct lguest_data __user *lguest_data;
- struct task_struct *tsk;
- struct mm_struct *mm; /* == tsk->mm, but that becomes NULL on exit */
struct lg_cpu cpus[NR_CPUS];
unsigned int nr_cpus;
void __user *mem_base;
unsigned long kernel_address;
u32 cr2;
- int halted;
int ts;
u32 esp1;
u8 ss1;
- /* Do we need to stop what we're doing and return to userspace? */
- int break_out;
- wait_queue_head_t break_wq;
-
/* Bitmap of what has changed: see CHANGED_* above. */
int changed;
struct lguest_pages *last_pages;
* LHREQ_BREAK and the value "1" to /dev/lguest to do this. Once the Launcher
* has done whatever needs attention, it writes LHREQ_BREAK and "0" to release
* the Waker. */
-static int break_guest_out(struct lguest *lg, const unsigned long __user *input)
+static int break_guest_out(struct lg_cpu *cpu, const unsigned long __user*input)
{
unsigned long on;
return -EFAULT;
if (on) {
- lg->break_out = 1;
+ cpu->break_out = 1;
/* Pop it out of the Guest (may be running on different CPU) */
- wake_up_process(lg->tsk);
+ wake_up_process(cpu->tsk);
/* Wait for them to reset it */
- return wait_event_interruptible(lg->break_wq, !lg->break_out);
+ return wait_event_interruptible(cpu->break_wq, !cpu->break_out);
} else {
- lg->break_out = 0;
- wake_up(&lg->break_wq);
+ cpu->break_out = 0;
+ wake_up(&cpu->break_wq);
return 0;
}
}
cpu = &lg->cpus[cpu_id];
/* If you're not the task which owns the Guest, go away. */
- if (current != lg->tsk)
+ if (current != cpu->tsk)
return -EPERM;
/* If the guest is already dead, we indicate why */
* address. */
lguest_arch_setup_regs(cpu, start_ip);
+ /* Initialize the queue for the waker to wait on */
+ init_waitqueue_head(&cpu->break_wq);
+
+ /* We keep a pointer to the Launcher task (ie. current task) for when
+ * other Guests want to wake this one (inter-Guest I/O). */
+ cpu->tsk = current;
+
+ /* We need to keep a pointer to the Launcher's memory map, because if
+ * the Launcher dies we need to clean it up. If we don't keep a
+ * reference, it is destroyed before close() is called. */
+ cpu->mm = get_task_mm(cpu->tsk);
+
return 0;
}
if (err)
goto free_regs;
- /* We keep a pointer to the Launcher task (ie. current task) for when
- * other Guests want to wake this one (inter-Guest I/O). */
- lg->tsk = current;
- /* We need to keep a pointer to the Launcher's memory map, because if
- * the Launcher dies we need to clean it up. If we don't keep a
- * reference, it is destroyed before close() is called. */
- lg->mm = get_task_mm(lg->tsk);
-
- /* Initialize the queue for the waker to wait on */
- init_waitqueue_head(&lg->break_wq);
-
/* We remember which CPU's pages this Guest used last, for optimization
* when the same Guest runs on the same CPU twice. */
lg->last_pages = NULL;
return -ENOENT;
/* If you're not the task which owns the Guest, you can only break */
- if (lg && current != lg->tsk && req != LHREQ_BREAK)
+ if (lg && current != cpu->tsk && req != LHREQ_BREAK)
return -EPERM;
switch (req) {
case LHREQ_IRQ:
return user_send_irq(cpu, input);
case LHREQ_BREAK:
- return break_guest_out(lg, input);
+ return break_guest_out(cpu, input);
default:
return -EINVAL;
}
/* We need the big lock, to protect from inter-guest I/O and other
* Launchers initializing guests. */
mutex_lock(&lguest_lock);
+
+ /* Free up the shadow page tables for the Guest. */
+ free_guest_pagetable(lg);
+
for (i = 0; i < lg->nr_cpus; i++) {
/* Cancels the hrtimer set via LHCALL_SET_CLOCKEVENT. */
hrtimer_cancel(&lg->cpus[i].hrt);
/* We can free up the register page we allocated. */
free_page(lg->cpus[i].regs_page);
+ /* Now all the memory cleanups are done, it's safe to release
+ * the Launcher's memory management structure. */
+ mmput(lg->cpus[i].mm);
}
- /* Free up the shadow page tables for the Guest. */
- free_guest_pagetable(lg);
- /* Now all the memory cleanups are done, it's safe to release the
- * Launcher's memory management structure. */
- mmput(lg->mm);
/* If lg->dead doesn't contain an error code it will be NULL or a
* kmalloc()ed string, either of which is ok to hand to kfree(). */
if (!IS_ERR(lg->dead))