From 9a687d1fe3af460cdc39c3ed08d1e33cc99b8141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Date: Fri, 2 Feb 2024 11:00:31 +0100 Subject: [PATCH] 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 12942375be4..ec0d4b1ab9f 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 6411b790a2b..9d9a64dd29e 100644 --- a/sys/x86/xen/hvm.c +++ b/sys/x86/xen/hvm.c @@ -41,8 +41,10 @@ #include +#include #include #include +#include #include #include @@ -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 75c345ff3a2..3c22d9e5cf6 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); } }