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>
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 0cc251c..2ef64a2 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -323,7 +323,9 @@
 		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 @@
 	}
 	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(). :*/