]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
xen: Setup hypercall page for PVH
authorJuergen Gross <jgross@suse.com>
Fri, 7 Dec 2018 12:11:39 +0000 (13:11 +0100)
committerDaniel Kiper <daniel.kiper@oracle.com>
Wed, 12 Dec 2018 11:03:27 +0000 (12:03 +0100)
Add the needed code to setup the hypercall page for calling into the
Xen hypervisor.

Import the XEN_HVM_DEBUGCONS_IOPORT define from Xen unstable into
include/xen/arch-x86/xen.h

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Hans van Kranenburg <hans@knorrie.org>
grub-core/kern/i386/xen/pvh.c
include/xen/arch-x86/xen.h

index 4f629b15eb13e7730a7558c99dd9d081c5d2165c..a2554fb1d80b398a49ed503d4aa848e88b41f15d 100644 (file)
 #include <grub/misc.h>
 #include <grub/memory.h>
 #include <grub/mm.h>
+#include <grub/i386/cpuid.h>
+#include <grub/i386/io.h>
 #include <grub/xen.h>
 #include <xen/hvm/start_info.h>
 #include <grub/machine/kernel.h>
 
 grub_uint64_t grub_rsdp_addr;
 
+static char hypercall_page[GRUB_XEN_PAGE_SIZE]
+  __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE)));
+
+static grub_uint32_t xen_cpuid_base;
+
+static void
+grub_xen_cons_msg (const char *msg)
+{
+  const char *c;
+
+  for (c = msg; *c; c++)
+    grub_outb (*c, XEN_HVM_DEBUGCONS_IOPORT);
+}
+
+static void
+grub_xen_panic (const char *msg)
+{
+  grub_xen_cons_msg (msg);
+  grub_xen_cons_msg ("System halted!\n");
+
+  asm volatile ("cli");
+
+  while (1)
+    {
+      asm volatile ("hlt");
+    }
+}
+
+static void
+grub_xen_cpuid_base (void)
+{
+  grub_uint32_t base, eax, signature[3];
+
+  for (base = 0x40000000; base < 0x40010000; base += 0x100)
+    {
+      grub_cpuid (base, eax, signature[0], signature[1], signature[2]);
+      if (!grub_memcmp ("XenVMMXenVMM", signature, 12) && (eax - base) >= 2)
+       {
+         xen_cpuid_base = base;
+         return;
+       }
+    }
+
+  grub_xen_panic ("Found no Xen signature!\n");
+}
+
+static void
+grub_xen_setup_hypercall_page (void)
+{
+  grub_uint32_t msr, addr, eax, ebx, ecx, edx;
+
+  /* Get base address of Xen-specific MSRs. */
+  grub_cpuid (xen_cpuid_base + 2, eax, ebx, ecx, edx);
+  msr = ebx;
+  addr = (grub_uint32_t) (&hypercall_page);
+
+  /* Specify hypercall page address for Xen. */
+  asm volatile ("wrmsr" : : "c" (msr), "a" (addr), "d" (0) : "memory");
+}
+
+int
+grub_xen_hypercall (grub_uint32_t callno, grub_uint32_t a0,
+                   grub_uint32_t a1, grub_uint32_t a2,
+                   grub_uint32_t a3, grub_uint32_t a4,
+                   grub_uint32_t a5 __attribute__ ((unused)))
+{
+  grub_uint32_t res;
+
+  asm volatile ("call *%[callno]"
+               : "=a" (res), "+b" (a0), "+c" (a1), "+d" (a2),
+                 "+S" (a3), "+D" (a4)
+               : [callno] "a" (&hypercall_page[callno * 32])
+               : "memory");
+  return res;
+}
+
 void
 grub_xen_setup_pvh (void)
 {
+  grub_xen_cpuid_base ();
+  grub_xen_setup_hypercall_page ();
 }
 
 grub_err_t
index f35804b88d91fe1df6e078980ae027cf237e5d31..56be26cb65a988eb960ea3d5034e9160c40b86ce 100644 (file)
@@ -260,6 +260,13 @@ typedef struct arch_shared_info arch_shared_info_t;
 #define XEN_CPUID          XEN_EMULATE_PREFIX "cpuid"
 #endif
 
+/*
+ * Debug console IO port, also called "port E9 hack". Each character written
+ * to this IO port will be printed on the hypervisor console, subject to log
+ * level restrictions.
+ */
+#define XEN_HVM_DEBUGCONS_IOPORT 0xe9
+
 #endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
 
 /*