/*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; } }