diff options
author | Jes Sorensen <jes@sgi.com> | 2007-10-21 21:03:31 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2007-10-23 01:49:52 -0400 |
commit | b410e7b1499c49513cab18275db8a8ab549d9e09 (patch) | |
tree | 8a71fa34660f5ccc9d71677137c5ae211a38bbf2 /drivers/lguest/x86 | |
parent | cc6d4fbcef328acdc9fa7023e69f39f753f72fe1 (diff) |
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>
Diffstat (limited to 'drivers/lguest/x86')
-rw-r--r-- | drivers/lguest/x86/core.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 0cc251cbc72a..2ef64a2734d3 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
@@ -323,7 +323,9 @@ void lguest_arch_handle_trap(struct lguest *lg) | |||
323 | cond_resched(); | 323 | cond_resched(); |
324 | return; | 324 | return; |
325 | case LGUEST_TRAP_ENTRY: | 325 | case LGUEST_TRAP_ENTRY: |
326 | lg->hcall = lg->regs; | 326 | /* Our 'struct hcall_args' maps directly over our regs: we set |
327 | * up the pointer now to indicate a hypercall is pending. */ | ||
328 | lg->hcall = (struct hcall_args *)lg->regs; | ||
327 | return; | 329 | return; |
328 | } | 330 | } |
329 | 331 | ||
@@ -475,3 +477,61 @@ void __exit lguest_arch_host_fini(void) | |||
475 | } | 477 | } |
476 | unlock_cpu_hotplug(); | 478 | unlock_cpu_hotplug(); |
477 | } | 479 | } |
480 | |||
481 | |||
482 | /*H:122 The i386-specific hypercalls simply farm out to the right functions. */ | ||
483 | int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args) | ||
484 | { | ||
485 | switch (args->arg0) { | ||
486 | case LHCALL_LOAD_GDT: | ||
487 | load_guest_gdt(lg, args->arg1, args->arg2); | ||
488 | break; | ||
489 | case LHCALL_LOAD_IDT_ENTRY: | ||
490 | load_guest_idt_entry(lg, args->arg1, args->arg2, args->arg3); | ||
491 | break; | ||
492 | case LHCALL_LOAD_TLS: | ||
493 | guest_load_tls(lg, args->arg1); | ||
494 | break; | ||
495 | default: | ||
496 | /* Bad Guest. Bad! */ | ||
497 | return -EIO; | ||
498 | } | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /*H:126 i386-specific hypercall initialization: */ | ||
503 | int lguest_arch_init_hypercalls(struct lguest *lg) | ||
504 | { | ||
505 | u32 tsc_speed; | ||
506 | |||
507 | /* The pointer to the Guest's "struct lguest_data" is the only | ||
508 | * argument. We check that address now. */ | ||
509 | if (!lguest_address_ok(lg, lg->hcall->arg1, sizeof(*lg->lguest_data))) | ||
510 | return -EFAULT; | ||
511 | |||
512 | /* Having checked it, we simply set lg->lguest_data to point straight | ||
513 | * into the Launcher's memory at the right place and then use | ||
514 | * copy_to_user/from_user from now on, instead of lgread/write. I put | ||
515 | * this in to show that I'm not immune to writing stupid | ||
516 | * optimizations. */ | ||
517 | lg->lguest_data = lg->mem_base + lg->hcall->arg1; | ||
518 | |||
519 | /* We insist that the Time Stamp Counter exist and doesn't change with | ||
520 | * cpu frequency. Some devious chip manufacturers decided that TSC | ||
521 | * changes could be handled in software. I decided that time going | ||
522 | * backwards might be good for benchmarks, but it's bad for users. | ||
523 | * | ||
524 | * We also insist that the TSC be stable: the kernel detects unreliable | ||
525 | * TSCs for its own purposes, and we use that here. */ | ||
526 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable()) | ||
527 | tsc_speed = tsc_khz; | ||
528 | else | ||
529 | tsc_speed = 0; | ||
530 | if (put_user(tsc_speed, &lg->lguest_data->tsc_khz)) | ||
531 | return -EFAULT; | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | /* Now we've examined the hypercall code; our Guest can make requests. There | ||
536 | * is one other way we can do things for the Guest, as we see in | ||
537 | * emulate_insn(). :*/ | ||