/*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 lg_cpu *cpu, unsigned long __user *user) { /* We stop running once the Guest is dead. */ while (!cpu->lg->dead) { /* First we run any hypercalls the Guest wants done. */ 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 (cpu->pending_notify) { if (put_user(cpu->pending_notify, user)) return -EFAULT; return sizeof(cpu->pending_notify); } /* Check for signals */ if (signal_pending(current)) return -ERESTARTSYS; /* If Waker set break_out, return to Launcher. */ 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(cpu); /* All long-lived kernel loops need to check with this horrible * thing called the freezer. If the Host is trying to suspend, * it stops us. */ try_to_freeze(); /* Just make absolutely sure the Guest is still alive. One of * those hypercalls could have been fatal, for example. */ if (cpu->lg->dead) break; /* If the Guest asked to be stopped, we sleep. The Guest's * clock timer or LHREQ_BREAK from the Waker will wake us. */ if (cpu->halted) { set_current_state(TASK_INTERRUPTIBLE); schedule(); continue; } /* OK, now we're ready to jump into the Guest. First we put up * the "Do Not Disturb" sign: */ local_irq_disable(); /* Actually run the Guest until something happens. */ 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(cpu); } /* Special case: Guest is 'dead' but wants a reboot. */ if (cpu->lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; /* The Guest is dead => "No such file or directory" */ return -ENOENT; }
/*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 lg_cpu *cpu, unsigned long __user *user) { /* We stop running once the Guest is dead. */ while (!cpu->lg->dead) { unsigned int irq; bool more; /* First we run any hypercalls the Guest wants done. */ if (cpu->hcall) do_hypercalls(cpu); /* * It's possible the Guest did a NOTIFY hypercall to the * Launcher. */ if (cpu->pending_notify) { /* * Does it just needs to write to a registered * eventfd (ie. the appropriate virtqueue thread)? */ if (!send_notify_to_eventfd(cpu)) { /* OK, we tell the main Laucher. */ if (put_user(cpu->pending_notify, user)) return -EFAULT; return sizeof(cpu->pending_notify); } } /* Check for signals */ if (signal_pending(current)) return -ERESTARTSYS; /* * 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. */ irq = interrupt_pending(cpu, &more); if (irq < LGUEST_IRQS) try_deliver_interrupt(cpu, irq, more); /* * All long-lived kernel loops need to check with this horrible * thing called the freezer. If the Host is trying to suspend, * it stops us. */ try_to_freeze(); /* * Just make absolutely sure the Guest is still alive. One of * those hypercalls could have been fatal, for example. */ if (cpu->lg->dead) break; /* * If the Guest asked to be stopped, we sleep. The Guest's * clock timer will wake us. */ if (cpu->halted) { set_current_state(TASK_INTERRUPTIBLE); /* * Just before we sleep, make sure no interrupt snuck in * which we should be doing. */ if (interrupt_pending(cpu, &more) < LGUEST_IRQS) set_current_state(TASK_RUNNING); else schedule(); continue; } /* * OK, now we're ready to jump into the Guest. First we put up * the "Do Not Disturb" sign: */ local_irq_disable(); /* Actually run the Guest until something happens. */ 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(cpu); } /* Special case: Guest is 'dead' but wants a reboot. */ if (cpu->lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; /* The Guest is dead => "No such file or directory" */ return -ENOENT; }
int run_guest(struct lg_cpu *cpu, unsigned long __user *user) { while (!cpu->lg->dead) { unsigned int irq; bool more; if (cpu->hcall) do_hypercalls(cpu); if (cpu->pending_notify) { if (!send_notify_to_eventfd(cpu)) { if (put_user(cpu->pending_notify, user)) return -EFAULT; return sizeof(cpu->pending_notify); } } if (signal_pending(current)) return -ERESTARTSYS; irq = interrupt_pending(cpu, &more); if (irq < LGUEST_IRQS) try_deliver_interrupt(cpu, irq, more); try_to_freeze(); if (cpu->lg->dead) break; if (cpu->halted) { set_current_state(TASK_INTERRUPTIBLE); if (interrupt_pending(cpu, &more) < LGUEST_IRQS) set_current_state(TASK_RUNNING); else schedule(); continue; } local_irq_disable(); lguest_arch_run_guest(cpu); local_irq_enable(); lguest_arch_handle_trap(cpu); } if (cpu->lg->dead == ERR_PTR(-ERESTART)) return -ERESTART; return -ENOENT; }