Make hypercalls arch-independent.
Clean up the hypercall code to make the code in hypercalls.c architecture independent. First process the common hypercalls and then call lguest_arch_do_hcall() if the call hasn't been handled. Rename struct hcall_ring to hcall_args. This patch requires the previous patch which reorganize the layout of struct lguest_regs on i386 so they match the layout of struct hcall_args. Signed-off-by: Jes Sorensen <jes@sgi.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Rusty Russell
parent
cc6d4fbcef
commit
b410e7b149
@ -323,7 +323,9 @@ void lguest_arch_handle_trap(struct lguest *lg)
|
||||
cond_resched();
|
||||
return;
|
||||
case LGUEST_TRAP_ENTRY:
|
||||
lg->hcall = lg->regs;
|
||||
/* Our 'struct hcall_args' maps directly over our regs: we set
|
||||
* up the pointer now to indicate a hypercall is pending. */
|
||||
lg->hcall = (struct hcall_args *)lg->regs;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -475,3 +477,61 @@ void __exit lguest_arch_host_fini(void)
|
||||
}
|
||||
unlock_cpu_hotplug();
|
||||
}
|
||||
|
||||
|
||||
/*H:122 The i386-specific hypercalls simply farm out to the right functions. */
|
||||
int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args)
|
||||
{
|
||||
switch (args->arg0) {
|
||||
case LHCALL_LOAD_GDT:
|
||||
load_guest_gdt(lg, args->arg1, args->arg2);
|
||||
break;
|
||||
case LHCALL_LOAD_IDT_ENTRY:
|
||||
load_guest_idt_entry(lg, args->arg1, args->arg2, args->arg3);
|
||||
break;
|
||||
case LHCALL_LOAD_TLS:
|
||||
guest_load_tls(lg, args->arg1);
|
||||
break;
|
||||
default:
|
||||
/* Bad Guest. Bad! */
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*H:126 i386-specific hypercall initialization: */
|
||||
int lguest_arch_init_hypercalls(struct lguest *lg)
|
||||
{
|
||||
u32 tsc_speed;
|
||||
|
||||
/* The pointer to the Guest's "struct lguest_data" is the only
|
||||
* argument. We check that address now. */
|
||||
if (!lguest_address_ok(lg, lg->hcall->arg1, sizeof(*lg->lguest_data)))
|
||||
return -EFAULT;
|
||||
|
||||
/* Having checked it, we simply set lg->lguest_data to point straight
|
||||
* into the Launcher's memory at the right place and then use
|
||||
* copy_to_user/from_user from now on, instead of lgread/write. I put
|
||||
* this in to show that I'm not immune to writing stupid
|
||||
* optimizations. */
|
||||
lg->lguest_data = lg->mem_base + lg->hcall->arg1;
|
||||
|
||||
/* We insist that the Time Stamp Counter exist and doesn't change with
|
||||
* cpu frequency. Some devious chip manufacturers decided that TSC
|
||||
* changes could be handled in software. I decided that time going
|
||||
* backwards might be good for benchmarks, but it's bad for users.
|
||||
*
|
||||
* We also insist that the TSC be stable: the kernel detects unreliable
|
||||
* TSCs for its own purposes, and we use that here. */
|
||||
if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
|
||||
tsc_speed = tsc_khz;
|
||||
else
|
||||
tsc_speed = 0;
|
||||
if (put_user(tsc_speed, &lg->lguest_data->tsc_khz))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Now we've examined the hypercall code; our Guest can make requests. There
|
||||
* is one other way we can do things for the Guest, as we see in
|
||||
* emulate_insn(). :*/
|
||||
|
Reference in New Issue
Block a user