Example #1
0
/*H:100
 * Hypercalls
 *
 * Remember from the Guest, hypercalls come in two flavors: normal and
 * asynchronous.  This file handles both of types.
 */
void do_hypercalls(struct lg_cpu *cpu)
{
    /* Not initialized yet?  This hypercall must do it. */
    if (unlikely(!cpu->lg->lguest_data)) {
        /* Set up the "struct lguest_data" */
        initialize(cpu);
        /* Hcall is done. */
        cpu->hcall = NULL;
        return;
    }

    /* The Guest has initialized.
     *
     * Look in the hypercall ring for the async hypercalls: */
    do_async_hcalls(cpu);

    /* If we stopped reading the hypercall ring because the Guest did a
     * NOTIFY to the Launcher, we want to return now.  Otherwise we do
     * the hypercall. */
    if (!cpu->pending_notify) {
        do_hcall(cpu, cpu->hcall);
        /* Tricky point: we reset the hcall pointer to mark the
         * hypercall as "done".  We use the hcall pointer rather than
         * the trap number to indicate a hypercall is pending.
         * Normally it doesn't matter: the Guest will run again and
         * update the trap number before we come back here.
         *
         * However, if we are signalled or the Guest sends I/O to the
         * Launcher, the run_guest() loop will exit without running the
         * Guest.  When it comes back it would try to re-run the
         * hypercall.  Finding that bug sucked. */
        cpu->hcall = NULL;
    }
}
void do_hypercalls(struct lg_cpu *cpu)
{
	
	if (unlikely(!cpu->lg->lguest_data)) {
		
		initialize(cpu);
		
		cpu->hcall = NULL;
		return;
	}

	do_async_hcalls(cpu);

	if (!cpu->pending_notify) {
		do_hcall(cpu, cpu->hcall);
		cpu->hcall = NULL;
	}
}