git: 9a687d1fe3af - main - x86/xen: introduce a Xen early init function

From: Roger Pau Monné <royger_at_FreeBSD.org>
Date: Thu, 22 Feb 2024 10:31:23 UTC
The branch main has been updated by royger:

URL: https://cgit.FreeBSD.org/src/commit/?id=9a687d1fe3af460cdc39c3ed08d1e33cc99b8141

commit 9a687d1fe3af460cdc39c3ed08d1e33cc99b8141
Author:     Roger Pau Monné <royger@FreeBSD.org>
AuthorDate: 2024-02-02 10:00:31 +0000
Commit:     Roger Pau Monné <royger@FreeBSD.org>
CommitDate: 2024-02-22 10:08:04 +0000

    x86/xen: introduce a Xen early init function
    
    Start by moving the hyeprcall setup to such function.
    
    The aim is to have a function that does all the required Xen early
    initialization for both HVM and PVH, instead of having it scattered across
    different paths.
    
    Sponsored by: Cloud Software Group
    Reviewed by: markj
    Differential revision: https://reviews.freebsd.org/D43932
---
 sys/x86/include/xen/xen-os.h |  3 +++
 sys/x86/xen/hvm.c            | 48 ++++++++++++++++++++++++++++++++++++++++++++
 sys/x86/xen/pv.c             |  9 ++++-----
 3 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/sys/x86/include/xen/xen-os.h b/sys/x86/include/xen/xen-os.h
index 12942375be43..ec0d4b1ab9f1 100644
--- a/sys/x86/include/xen/xen-os.h
+++ b/sys/x86/include/xen/xen-os.h
@@ -96,6 +96,9 @@ xen_pv_nics_disabled(void)
 
 bool xen_has_iommu_maps(void);
 
+/* (Very) early initialization. */
+void xen_early_init(void);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _MACHINE_X86_XEN_XEN_OS_H_ */
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
index 6411b790a2be..9d9a64dd29ea 100644
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -41,8 +41,10 @@
 
 #include <dev/pci/pcivar.h>
 
+#include <machine/_inttypes.h>
 #include <machine/cpufunc.h>
 #include <machine/cpu.h>
+#include <machine/md_var.h>
 #include <machine/smp.h>
 
 #include <x86/apicreg.h>
@@ -184,6 +186,52 @@ out:
 	return (0);
 }
 
+/*
+ * Translate linear to physical address when still running on the bootloader
+ * created page-tables.
+ */
+static vm_paddr_t
+early_init_vtop(void *addr)
+{
+
+	/*
+	 * Using a KASSERT won't print anything, as this is before console
+	 * initialization.
+	 */
+	if (__predict_false((uintptr_t)addr < KERNBASE)) {
+		xc_printf("invalid linear address: %#lx\n", (uintptr_t)addr);
+		halt();
+	}
+
+	return ((uintptr_t)addr - KERNBASE
+#ifdef __amd64__
+	    + kernphys - KERNLOAD
+#endif
+	    );
+}
+
+/* Early initialization when running as a Xen guest. */
+void
+xen_early_init(void)
+{
+	uint32_t regs[4];
+
+	xen_cpuid_base = xen_hvm_cpuid_base();
+	if (xen_cpuid_base == 0)
+		return;
+
+	/* Find the hypercall pages. */
+	do_cpuid(xen_cpuid_base + 2, regs);
+	if (regs[0] != 1) {
+		xc_printf("Invalid number of hypercall pages %u\n",
+		    regs[0]);
+		vm_guest = VM_GUEST_VM;
+		return;
+	}
+
+	wrmsr(regs[1], early_init_vtop(&hypercall_page));
+}
+
 static void
 xen_hvm_init_shared_info_page(void)
 {
diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c
index 75c345ff3a2c..3c22d9e5cf6f 100644
--- a/sys/x86/xen/pv.c
+++ b/sys/x86/xen/pv.c
@@ -162,14 +162,13 @@ hammer_time_xen(vm_paddr_t start_info_paddr)
 	struct xen_add_to_physmap xatp;
 	uint64_t physfree;
 	char *kenv;
-	int rc;
 
 	if (isxen()) {
 		vm_guest = VM_GUEST_XEN;
-		rc = xen_hvm_init_hypercall_stubs(XEN_HVM_INIT_EARLY);
-		if (rc) {
-			xc_printf("ERROR: failed to initialize hypercall page: %d\n",
-			    rc);
+		xen_early_init();
+		if (xen_cpuid_base == 0) {
+			xc_printf(
+			    "ERROR: failed to initialize hypercall page\n");
 			HYPERVISOR_shutdown(SHUTDOWN_crash);
 		}
 	}