aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2024-02-02 10:00:31 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2024-02-22 10:08:04 +0000
commit9a687d1fe3af460cdc39c3ed08d1e33cc99b8141 (patch)
tree6cc92b5f11baf025cd0898590ba7c490386b9892
parent848e2719af508516452b447047ddf6642ce42d0f (diff)
downloadsrc-9a687d1fe3af460cdc39c3ed08d1e33cc99b8141.tar.gz
src-9a687d1fe3af460cdc39c3ed08d1e33cc99b8141.zip
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
-rw-r--r--sys/x86/include/xen/xen-os.h3
-rw-r--r--sys/x86/xen/hvm.c48
-rw-r--r--sys/x86/xen/pv.c9
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);
}
}