|
@@ -29,8 +29,10 @@
|
|
|
|
|
|
/*H:120 This is the core hypercall routine: where the Guest gets what it wants.
|
|
/*H:120 This is the core hypercall routine: where the Guest gets what it wants.
|
|
* Or gets killed. Or, in the case of LHCALL_CRASH, both. */
|
|
* Or gets killed. Or, in the case of LHCALL_CRASH, both. */
|
|
-static void do_hcall(struct lguest *lg, struct hcall_args *args)
|
|
|
|
|
|
+static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
|
|
{
|
|
{
|
|
|
|
+ struct lguest *lg = cpu->lg;
|
|
|
|
+
|
|
switch (args->arg0) {
|
|
switch (args->arg0) {
|
|
case LHCALL_FLUSH_ASYNC:
|
|
case LHCALL_FLUSH_ASYNC:
|
|
/* This call does nothing, except by breaking out of the Guest
|
|
/* This call does nothing, except by breaking out of the Guest
|
|
@@ -93,7 +95,7 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
/* It should be an architecture-specific hypercall. */
|
|
/* It should be an architecture-specific hypercall. */
|
|
- if (lguest_arch_do_hcall(lg, args))
|
|
|
|
|
|
+ if (lguest_arch_do_hcall(cpu, args))
|
|
kill_guest(lg, "Bad hypercall %li\n", args->arg0);
|
|
kill_guest(lg, "Bad hypercall %li\n", args->arg0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -106,10 +108,11 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
|
|
* Guest put them in the ring, but we also promise the Guest that they will
|
|
* Guest put them in the ring, but we also promise the Guest that they will
|
|
* happen before any normal hypercall (which is why we check this before
|
|
* happen before any normal hypercall (which is why we check this before
|
|
* checking for a normal hcall). */
|
|
* checking for a normal hcall). */
|
|
-static void do_async_hcalls(struct lguest *lg)
|
|
|
|
|
|
+static void do_async_hcalls(struct lg_cpu *cpu)
|
|
{
|
|
{
|
|
unsigned int i;
|
|
unsigned int i;
|
|
u8 st[LHCALL_RING_SIZE];
|
|
u8 st[LHCALL_RING_SIZE];
|
|
|
|
+ struct lguest *lg = cpu->lg;
|
|
|
|
|
|
/* For simplicity, we copy the entire call status array in at once. */
|
|
/* For simplicity, we copy the entire call status array in at once. */
|
|
if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)))
|
|
if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)))
|
|
@@ -121,7 +124,7 @@ static void do_async_hcalls(struct lguest *lg)
|
|
/* We remember where we were up to from last time. This makes
|
|
/* We remember where we were up to from last time. This makes
|
|
* sure that the hypercalls are done in the order the Guest
|
|
* sure that the hypercalls are done in the order the Guest
|
|
* places them in the ring. */
|
|
* places them in the ring. */
|
|
- unsigned int n = lg->next_hcall;
|
|
|
|
|
|
+ unsigned int n = cpu->next_hcall;
|
|
|
|
|
|
/* 0xFF means there's no call here (yet). */
|
|
/* 0xFF means there's no call here (yet). */
|
|
if (st[n] == 0xFF)
|
|
if (st[n] == 0xFF)
|
|
@@ -129,8 +132,8 @@ static void do_async_hcalls(struct lguest *lg)
|
|
|
|
|
|
/* OK, we have hypercall. Increment the "next_hcall" cursor,
|
|
/* OK, we have hypercall. Increment the "next_hcall" cursor,
|
|
* and wrap back to 0 if we reach the end. */
|
|
* and wrap back to 0 if we reach the end. */
|
|
- if (++lg->next_hcall == LHCALL_RING_SIZE)
|
|
|
|
- lg->next_hcall = 0;
|
|
|
|
|
|
+ if (++cpu->next_hcall == LHCALL_RING_SIZE)
|
|
|
|
+ cpu->next_hcall = 0;
|
|
|
|
|
|
/* Copy the hypercall arguments into a local copy of
|
|
/* Copy the hypercall arguments into a local copy of
|
|
* the hcall_args struct. */
|
|
* the hcall_args struct. */
|
|
@@ -141,7 +144,7 @@ static void do_async_hcalls(struct lguest *lg)
|
|
}
|
|
}
|
|
|
|
|
|
/* Do the hypercall, same as a normal one. */
|
|
/* Do the hypercall, same as a normal one. */
|
|
- do_hcall(lg, &args);
|
|
|
|
|
|
+ do_hcall(cpu, &args);
|
|
|
|
|
|
/* Mark the hypercall done. */
|
|
/* Mark the hypercall done. */
|
|
if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) {
|
|
if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) {
|
|
@@ -158,16 +161,17 @@ static void do_async_hcalls(struct lguest *lg)
|
|
|
|
|
|
/* Last of all, we look at what happens first of all. The very first time the
|
|
/* Last of all, we look at what happens first of all. The very first time the
|
|
* Guest makes a hypercall, we end up here to set things up: */
|
|
* Guest makes a hypercall, we end up here to set things up: */
|
|
-static void initialize(struct lguest *lg)
|
|
|
|
|
|
+static void initialize(struct lg_cpu *cpu)
|
|
{
|
|
{
|
|
|
|
+ struct lguest *lg = cpu->lg;
|
|
/* You can't do anything until you're initialized. The Guest knows the
|
|
/* You can't do anything until you're initialized. The Guest knows the
|
|
* rules, so we're unforgiving here. */
|
|
* rules, so we're unforgiving here. */
|
|
- if (lg->hcall->arg0 != LHCALL_LGUEST_INIT) {
|
|
|
|
- kill_guest(lg, "hypercall %li before INIT", lg->hcall->arg0);
|
|
|
|
|
|
+ if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
|
|
|
|
+ kill_guest(lg, "hypercall %li before INIT", cpu->hcall->arg0);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (lguest_arch_init_hypercalls(lg))
|
|
|
|
|
|
+ if (lguest_arch_init_hypercalls(cpu))
|
|
kill_guest(lg, "bad guest page %p", lg->lguest_data);
|
|
kill_guest(lg, "bad guest page %p", lg->lguest_data);
|
|
|
|
|
|
/* The Guest tells us where we're not to deliver interrupts by putting
|
|
/* The Guest tells us where we're not to deliver interrupts by putting
|
|
@@ -196,27 +200,27 @@ static void initialize(struct lguest *lg)
|
|
* Remember from the Guest, hypercalls come in two flavors: normal and
|
|
* Remember from the Guest, hypercalls come in two flavors: normal and
|
|
* asynchronous. This file handles both of types.
|
|
* asynchronous. This file handles both of types.
|
|
*/
|
|
*/
|
|
-void do_hypercalls(struct lguest *lg)
|
|
|
|
|
|
+void do_hypercalls(struct lg_cpu *cpu)
|
|
{
|
|
{
|
|
/* Not initialized yet? This hypercall must do it. */
|
|
/* Not initialized yet? This hypercall must do it. */
|
|
- if (unlikely(!lg->lguest_data)) {
|
|
|
|
|
|
+ if (unlikely(!cpu->lg->lguest_data)) {
|
|
/* Set up the "struct lguest_data" */
|
|
/* Set up the "struct lguest_data" */
|
|
- initialize(lg);
|
|
|
|
|
|
+ initialize(cpu);
|
|
/* Hcall is done. */
|
|
/* Hcall is done. */
|
|
- lg->hcall = NULL;
|
|
|
|
|
|
+ cpu->hcall = NULL;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/* The Guest has initialized.
|
|
/* The Guest has initialized.
|
|
*
|
|
*
|
|
* Look in the hypercall ring for the async hypercalls: */
|
|
* Look in the hypercall ring for the async hypercalls: */
|
|
- do_async_hcalls(lg);
|
|
|
|
|
|
+ do_async_hcalls(cpu);
|
|
|
|
|
|
/* If we stopped reading the hypercall ring because the Guest did a
|
|
/* If we stopped reading the hypercall ring because the Guest did a
|
|
* NOTIFY to the Launcher, we want to return now. Otherwise we do
|
|
* NOTIFY to the Launcher, we want to return now. Otherwise we do
|
|
* the hypercall. */
|
|
* the hypercall. */
|
|
- if (!lg->pending_notify) {
|
|
|
|
- do_hcall(lg, lg->hcall);
|
|
|
|
|
|
+ if (!cpu->lg->pending_notify) {
|
|
|
|
+ do_hcall(cpu, cpu->hcall);
|
|
/* Tricky point: we reset the hcall pointer to mark the
|
|
/* Tricky point: we reset the hcall pointer to mark the
|
|
* hypercall as "done". We use the hcall pointer rather than
|
|
* hypercall as "done". We use the hcall pointer rather than
|
|
* the trap number to indicate a hypercall is pending.
|
|
* the trap number to indicate a hypercall is pending.
|
|
@@ -227,7 +231,7 @@ void do_hypercalls(struct lguest *lg)
|
|
* Launcher, the run_guest() loop will exit without running the
|
|
* Launcher, the run_guest() loop will exit without running the
|
|
* Guest. When it comes back it would try to re-run the
|
|
* Guest. When it comes back it would try to re-run the
|
|
* hypercall. */
|
|
* hypercall. */
|
|
- lg->hcall = NULL;
|
|
|
|
|
|
+ cpu->hcall = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|