aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/hypercalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/hypercalls.c')
-rw-r--r--drivers/lguest/hypercalls.c48
1 files changed, 20 insertions, 28 deletions
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 8bde20934f91..0175a9f03347 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -241,19 +241,6 @@ static void initialize(struct lguest *lg)
241 * is one other way we can do things for the Guest, as we see in 241 * is one other way we can do things for the Guest, as we see in
242 * emulate_insn(). */ 242 * emulate_insn(). */
243 243
244/*H:110 Tricky point: we mark the hypercall as "done" once we've done it.
245 * Normally we don't need to do this: the Guest will run again and update the
246 * trap number before we come back around the run_guest() loop to
247 * do_hypercalls().
248 *
249 * However, if we are signalled or the Guest sends DMA to the Launcher, that
250 * loop will exit without running the Guest. When it comes back it would try
251 * to re-run the hypercall. */
252static void clear_hcall(struct lguest *lg)
253{
254 lg->regs->trapnum = 255;
255}
256
257/*H:100 244/*H:100
258 * Hypercalls 245 * Hypercalls
259 * 246 *
@@ -262,16 +249,12 @@ static void clear_hcall(struct lguest *lg)
262 */ 249 */
263void do_hypercalls(struct lguest *lg) 250void do_hypercalls(struct lguest *lg)
264{ 251{
265 /* Not initialized yet? */ 252 /* Not initialized yet? This hypercall must do it. */
266 if (unlikely(!lg->lguest_data)) { 253 if (unlikely(!lg->lguest_data)) {
267 /* Did the Guest make a hypercall? We might have come back for 254 /* Set up the "struct lguest_data" */
268 * some other reason (an interrupt, a different trap). */ 255 initialize(lg);
269 if (lg->regs->trapnum == LGUEST_TRAP_ENTRY) { 256 /* Hcall is done. */
270 /* Set up the "struct lguest_data" */ 257 lg->hcall = NULL;
271 initialize(lg);
272 /* The hypercall is done. */
273 clear_hcall(lg);
274 }
275 return; 258 return;
276 } 259 }
277 260
@@ -281,12 +264,21 @@ void do_hypercalls(struct lguest *lg)
281 do_async_hcalls(lg); 264 do_async_hcalls(lg);
282 265
283 /* If we stopped reading the hypercall ring because the Guest did a 266 /* If we stopped reading the hypercall ring because the Guest did a
284 * SEND_DMA to the Launcher, we want to return now. Otherwise if the 267 * SEND_DMA to the Launcher, we want to return now. Otherwise we do
285 * Guest asked us to do a hypercall, we do it. */ 268 * the hypercall. */
286 if (!lg->dma_is_pending && lg->regs->trapnum == LGUEST_TRAP_ENTRY) { 269 if (!lg->dma_is_pending) {
287 do_hcall(lg, lg->regs); 270 do_hcall(lg, lg->hcall);
288 /* The hypercall is done. */ 271 /* Tricky point: we reset the hcall pointer to mark the
289 clear_hcall(lg); 272 * hypercall as "done". We use the hcall pointer rather than
273 * the trap number to indicate a hypercall is pending.
274 * Normally it doesn't matter: the Guest will run again and
275 * update the trap number before we come back here.
276 *
277 * However, if we are signalled or the Guest sends DMA to the
278 * Launcher, the run_guest() loop will exit without running the
279 * Guest. When it comes back it would try to re-run the
280 * hypercall. */
281 lg->hcall = NULL;
290 } 282 }
291} 283}
292 284