FreeBSD Bugzilla – Attachment 247874 Details for
Bug 276421
Commit b0165dc4539fdfc84351a719b58850e4e7a6cbb6 inhibits initialization of Xen front and backends
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch v3
fix.patch (text/plain), 13.56 KB, created by
Roger Pau Monné
on 2024-01-23 09:12:32 UTC
(
hide
)
Description:
Patch v3
Filename:
MIME Type:
Creator:
Roger Pau Monné
Created:
2024-01-23 09:12:32 UTC
Size:
13.56 KB
patch
obsolete
>diff --git a/sys/dev/xen/console/xen_console.c b/sys/dev/xen/console/xen_console.c >index d232dd4e0c1c..934fa32915bb 100644 >--- a/sys/dev/xen/console/xen_console.c >+++ b/sys/dev/xen/console/xen_console.c >@@ -138,6 +138,12 @@ struct putchar_arg { > size_t n_next; > }; > >+void __weak_symbol >+xen_emergency_print(const char *str, size_t size) >+{ >+ HYPERVISOR_console_write(str, size); >+} >+ > static void > putchar(int c, void *arg) > { >@@ -150,12 +156,12 @@ putchar(int c, void *arg) > * We have no buffer, output directly to the > * console char by char. > */ >- HYPERVISOR_console_write((char *)&c, 1); >+ xen_emergency_print((char *)&c, 1); > } else { > pca->buf[pca->n_next++] = c; > if ((pca->size == pca->n_next) || (c = '\0')) { > /* Flush the buffer */ >- HYPERVISOR_console_write(pca->buf, pca->n_next); >+ xen_emergency_print(pca->buf, pca->n_next); > pca->n_next = 0; > } > } >@@ -185,10 +191,17 @@ xc_printf(const char *fmt, ...) > > #ifdef PRINTF_BUFR_SIZE > if (pca.n_next != 0) >- HYPERVISOR_console_write(buf, pca.n_next); >+ xen_emergency_print(buf, pca.n_next); > #endif > } > >+#ifdef EARLY_PRINTF >+void xen_early_putc(int ch) >+{ >+ xen_emergency_print((char *)&ch, 1); >+} >+#endif >+ > /*---------------------- Helpers for the console lock -----------------------*/ > /* > * The lock is not used when the kernel is panicing as it will never recover >diff --git a/sys/x86/include/xen/xen-os.h b/sys/x86/include/xen/xen-os.h >index 12942375be43..d3f21e2a6c45 100644 >--- a/sys/x86/include/xen/xen-os.h >+++ b/sys/x86/include/xen/xen-os.h >@@ -52,8 +52,6 @@ extern int xen_disable_pv_disks; > /* tunable for disabling PV nics */ > extern int xen_disable_pv_nics; > >-extern uint32_t xen_cpuid_base; >- > /* compatibility for accessing xen_ulong_t with atomics */ > #define atomic_clear_xen_ulong atomic_clear_long > #define atomic_set_xen_ulong atomic_set_long >@@ -96,6 +94,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/x86/identcpu.c b/sys/x86/x86/identcpu.c >index 9c82f9f8a882..221973abdfb9 100644 >--- a/sys/x86/x86/identcpu.c >+++ b/sys/x86/x86/identcpu.c >@@ -67,6 +67,8 @@ > #include <x86/isa/icu.h> > #include <x86/vmware.h> > >+#include <xen/xen-os.h> >+ > #ifdef __i386__ > #define IDENTBLUE_CYRIX486 0 > #define IDENTBLUE_IBMCPU 1 >@@ -1343,8 +1345,13 @@ SYSINIT(hook_tsc_freq, SI_SUB_CONFIGURE, SI_ORDER_ANY, hook_tsc_freq, NULL); > static struct { > const char *vm_cpuid; > int vm_guest; >+ void (*init)(void); > } vm_cpuids[] = { >- { "XenVMMXenVMM", VM_GUEST_XEN }, /* XEN */ >+ { "XenVMMXenVMM", VM_GUEST_XEN, >+#ifdef XENHVM >+ &xen_early_init, >+#endif >+ }, /* XEN */ > { "Microsoft Hv", VM_GUEST_HV }, /* Microsoft Hyper-V */ > { "VMwareVMware", VM_GUEST_VMWARE }, /* VMware VM */ > { "KVMKVMKVM", VM_GUEST_KVM }, /* KVM */ >@@ -1355,6 +1362,7 @@ static struct { > static void > identify_hypervisor_cpuid_base(void) > { >+ void (*init_fn)(void); > u_int leaf, regs[4]; > int i; > >@@ -1385,10 +1393,13 @@ identify_hypervisor_cpuid_base(void) > regs[0] = leaf + 1; > > if (regs[0] >= leaf) { >+ enum VM_GUEST prev_vm_guest = vm_guest; >+ > for (i = 0; i < nitems(vm_cpuids); i++) > if (strncmp((const char *)®s[1], > vm_cpuids[i].vm_cpuid, 12) == 0) { > vm_guest = vm_cpuids[i].vm_guest; >+ init_fn = vm_cpuids[i].init; > break; > } > >@@ -1397,7 +1408,7 @@ identify_hypervisor_cpuid_base(void) > * specific hypervisor, record the base, high value, > * and vendor identifier. > */ >- if (vm_guest != VM_GUEST_VM || leaf == 0x40000000) { >+ if (vm_guest != prev_vm_guest || leaf == 0x40000000) { > hv_base = leaf; > hv_high = regs[0]; > ((u_int *)&hv_vendor)[0] = regs[1]; >@@ -1409,11 +1420,25 @@ identify_hypervisor_cpuid_base(void) > * If we found a specific hypervisor, then > * we are finished. > */ >- if (vm_guest != VM_GUEST_VM) >- return; >+ if (vm_guest != VM_GUEST_VM && >+ /* >+ * Xen and other hypervisors can expose the >+ * HyperV signature in addition to the >+ * native one in order to support Viridian >+ * extensions for Windows guests. >+ * >+ * Do the full cpuid scan if HyperV is >+ * detected, as the native hypervisor is >+ * preferred. >+ */ >+ vm_guest != VM_GUEST_HV) >+ break; > } > } > } >+ >+ if (init_fn != NULL) >+ init_fn(); > } > > void >diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c >index b8125e230b6f..e78f10b68168 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> >@@ -95,6 +97,14 @@ TUNABLE_INT("hw.xen.disable_pv_nics", &xen_disable_pv_nics); > > /*---------------------- XEN Hypervisor Probe and Setup ----------------------*/ > >+void xen_emergency_print(const char *str, size_t size) >+{ >+ size_t i; >+ >+ for (i = 0; i < size; i++) >+ outb(XEN_HVM_DEBUGCONS_IOPORT, str[i]); >+} >+ > uint32_t xen_cpuid_base; > > static uint32_t >@@ -138,7 +148,7 @@ hypervisor_version(void) > uint32_t regs[4]; > int major, minor; > >- do_cpuid(xen_cpuid_base + 1, regs); >+ do_cpuid(hv_base + 1, regs); > > major = regs[0] >> 16; > minor = regs[0] & 0xffff; >@@ -148,62 +158,88 @@ hypervisor_version(void) > } > > /* >- * Allocate and fill in the hypcall page. >+ * Translate linear to physical address when still running on the bootloader >+ * created page-tables. > */ >-int >-xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type) >+static vm_paddr_t __nosanitizeaddress __nosanitizememory >+early_init_vtop(void *addr) > { >- uint32_t regs[4]; >- >- if (xen_cpuid_base != 0) >- /* Already setup. */ >- goto out; >- >- xen_cpuid_base = xen_hvm_cpuid_base(); >- if (xen_cpuid_base == 0) >- return (ENXIO); >+ return ((uintptr_t)addr - KERNBASE >+#ifdef __amd64__ >+ + kernphys - KERNLOAD >+#endif >+ ); >+} > >+static int >+map_shared_info(void) >+{ > /* >- * Find the hypercall pages. >+ * TODO shared info page should be mapped in an unpopulated (IOW: >+ * non-RAM) address. But finding one at this point in boot is >+ * complicated, hence re-use a RAM address for the time being. This >+ * sadly causes super-page shattering in the second stage translation >+ * page tables. > */ >- do_cpuid(xen_cpuid_base + 2, regs); >- if (regs[0] != 1) >- return (EINVAL); >+ static shared_info_t shared_page __attribute__((aligned(PAGE_SIZE))); >+ static struct xen_add_to_physmap xatp = { >+ .domid = DOMID_SELF, >+ .idx = 0, >+ .space = XENMAPSPACE_shared_info, >+ }; >+ int rc; > >- wrmsr(regs[1], (init_type == XEN_HVM_INIT_EARLY) >- ? (vm_paddr_t)((uintptr_t)&hypercall_page - KERNBASE) >- : vtophys(&hypercall_page)); >+ if (xatp.gpfn == 0) >+ xatp.gpfn = atop(early_init_vtop(&shared_page)); > >-out: >- hypervisor_version(); >- return (0); >+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); >+ if (rc != 0) { >+ printf("cannot map shared info page: %d\n", rc); >+ HYPERVISOR_shared_info = NULL; >+ } else if (HYPERVISOR_shared_info == NULL) >+ HYPERVISOR_shared_info = &shared_page; >+ >+ return (rc); > } > >-static void >-xen_hvm_init_shared_info_page(void) >+/* >+ * Populate the hypecall and shared pages. >+ */ >+void >+xen_early_init(void) > { >- struct xen_add_to_physmap xatp; >+ uint32_t regs[4]; >+ int rc; > >- if (xen_pv_domain()) { >- /* >- * Already setup in the PV case, shared_info is passed inside >- * of the start_info struct at start of day. >- */ >+#ifdef EARLY_PRINTF >+ early_putc = &xen_early_putc; >+#endif >+ >+ if (hv_high < 2) { >+ xc_printf("Invalid maximum leaves for hv_base\n"); >+ vm_guest = VM_GUEST_VM; > return; > } > >- if (HYPERVISOR_shared_info == NULL) { >- HYPERVISOR_shared_info = malloc(PAGE_SIZE, M_XENHVM, M_NOWAIT); >- if (HYPERVISOR_shared_info == NULL) >- panic("Unable to allocate Xen shared info page"); >+ /* >+ * Find the hypercall pages. >+ */ >+ do_cpuid(hv_base + 2, regs); >+ if (regs[0] != 1) { >+ xc_printf("Invalid number of hypercall pages %" PRIu32 "\n", >+ regs[0]); >+ vm_guest = VM_GUEST_VM; >+ return; > } > >- xatp.domid = DOMID_SELF; >- xatp.idx = 0; >- xatp.space = XENMAPSPACE_shared_info; >- xatp.gpfn = vtophys(HYPERVISOR_shared_info) >> PAGE_SHIFT; >- if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) >- panic("HYPERVISOR_memory_op failed"); >+ wrmsr(regs[1], early_init_vtop(&hypercall_page)); >+ >+ rc = map_shared_info(); >+ if (rc != 0) { >+ xc_printf("cannot map shared info page: %d\n", rc); >+ vm_guest = VM_GUEST_VM; >+ return; >+ } > } > > static int >@@ -322,32 +358,29 @@ xen_hvm_disable_emulated_devices(void) > static void > xen_hvm_init(enum xen_hvm_init_type init_type) > { >- int error; > int i; > > if (!xen_domain() || > init_type == XEN_HVM_INIT_CANCELLED_SUSPEND) > return; > >- error = xen_hvm_init_hypercall_stubs(init_type); >+ hypervisor_version(); > > switch (init_type) { > case XEN_HVM_INIT_LATE: >- if (error != 0) >- return; >- > setup_xen_features(); > #ifdef SMP > cpu_ops = xen_hvm_cpu_ops; > #endif > break; > case XEN_HVM_INIT_RESUME: >- if (error != 0) >- panic("Unable to init Xen hypercall stubs on resume"); >- > /* Clear stale vcpu_info. */ > CPU_FOREACH(i) > DPCPU_ID_SET(i, vcpu_info, NULL); >+ >+ if (map_shared_info() != 0) >+ panic("cannot map shared info page\n"); >+ > break; > default: > panic("Unsupported HVM initialization type"); >@@ -357,13 +390,6 @@ xen_hvm_init(enum xen_hvm_init_type init_type) > xen_evtchn_needs_ack = false; > xen_hvm_set_callback(NULL); > >- /* >- * On (PV)HVM domains we need to request the hypervisor to >- * fill the shared info page, for PVH guest the shared_info page >- * is passed inside the start_info struct and is already set, so this >- * functions are no-ops. >- */ >- xen_hvm_init_shared_info_page(); > xen_hvm_disable_emulated_devices(); > } > >@@ -412,8 +438,8 @@ xen_hvm_cpu_init(void) > * Set vCPU ID. If available fetch the ID from CPUID, if not just use > * the ACPI ID. > */ >- KASSERT(xen_cpuid_base != 0, ("Invalid base Xen CPUID leaf")); >- cpuid_count(xen_cpuid_base + 4, 0, regs); >+ KASSERT(hv_base != 0, ("Invalid base Xen CPUID leaf")); >+ cpuid_count(hv_base + 4, 0, regs); > KASSERT((regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) || > !xen_pv_domain(), > ("Xen PV domain without vcpu_id in cpuid")); >@@ -443,8 +469,8 @@ xen_has_iommu_maps(void) > { > uint32_t regs[4]; > >- KASSERT(xen_cpuid_base != 0, ("Invalid base Xen CPUID leaf")); >- cpuid_count(xen_cpuid_base + 4, 0, regs); >+ KASSERT(hv_base != 0, ("Invalid base Xen CPUID leaf")); >+ cpuid_count(hv_base + 4, 0, regs); > > return (regs[0] & XEN_HVM_CPUID_IOMMU_MAPPINGS); > } >diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c >index 9ea276caee81..7c41332d5b39 100644 >--- a/sys/x86/xen/pv.c >+++ b/sys/x86/xen/pv.c >@@ -159,20 +159,8 @@ uint64_t > hammer_time_xen(vm_paddr_t start_info_paddr) > { > struct hvm_modlist_entry *mod; >- 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); >- HYPERVISOR_shutdown(SHUTDOWN_crash); >- } >- } > > start_info = (struct hvm_start_info *)(start_info_paddr + KERNBASE); > if (start_info->magic != XEN_HVM_START_MAGIC_VALUE) { >@@ -211,19 +199,6 @@ hammer_time_xen(vm_paddr_t start_info_paddr) > PAGE_SIZE), physfree); > } > >- if (isxen()) { >- xatp.domid = DOMID_SELF; >- xatp.idx = 0; >- xatp.space = XENMAPSPACE_shared_info; >- xatp.gpfn = atop(physfree); >- if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) { >- xc_printf("ERROR: failed to setup shared_info page\n"); >- HYPERVISOR_shutdown(SHUTDOWN_crash); >- } >- HYPERVISOR_shared_info = (shared_info_t *)(physfree + KERNBASE); >- physfree += PAGE_SIZE; >- } >- > /* > * Init a static kenv using a free page. The contents will be filled > * from the parse_preload_data hook. >diff --git a/sys/x86/xen/xen_apic.c b/sys/x86/xen/xen_apic.c >index 4f2b03879227..994dc3e0804c 100644 >--- a/sys/x86/xen/xen_apic.c >+++ b/sys/x86/xen/xen_apic.c >@@ -343,8 +343,8 @@ xen_setup_cpus(void) > * that's faster than using event channels because it avoids the VM > * exit. > */ >- KASSERT(xen_cpuid_base != 0, ("Invalid base Xen CPUID leaf")); >- cpuid_count(xen_cpuid_base + 4, 0, regs); >+ KASSERT(hv_base != 0, ("Invalid base Xen CPUID leaf")); >+ cpuid_count(hv_base + 4, 0, regs); > if ((x2apic_mode && (regs[0] & XEN_HVM_CPUID_X2APIC_VIRT)) || > (!x2apic_mode && (regs[0] & XEN_HVM_CPUID_APIC_ACCESS_VIRT))) > return; >diff --git a/sys/xen/hvm.h b/sys/xen/hvm.h >index 3ff3ee3c51e6..f6d4292fd785 100644 >--- a/sys/xen/hvm.h >+++ b/sys/xen/hvm.h >@@ -96,7 +96,6 @@ enum xen_hvm_init_type { > XEN_HVM_INIT_RESUME, > }; > >-int xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type); > void xen_hvm_set_callback(device_t); > void xen_hvm_suspend(void); > void xen_hvm_resume(bool suspend_cancelled); >diff --git a/sys/xen/xen-os.h b/sys/xen/xen-os.h >index d7e9b3ca8632..b1465b112413 100644 >--- a/sys/xen/xen-os.h >+++ b/sys/xen/xen-os.h >@@ -151,6 +151,19 @@ int xenmem_free(device_t dev, int res_id, struct resource *res); > /* Debug/emergency function, prints directly to hypervisor console */ > void xc_printf(const char *, ...) __printflike(1, 2); > >+/* >+ * Emergency print function, can be defined per-arch, otherwise defaults to >+ * HYPERVISOR_console_write. Should not be called directly, use xc_printf >+ * instead. >+ */ >+void xen_emergency_print(const char *str, size_t size); >+ >+/* >+ * Early printk implementation based on xen_emergency_print. Only defined if >+ * EARLY_PRINTF is set. >+ */ >+void xen_early_putc(int ch); >+ > #ifndef xen_mb > #define xen_mb() mb() > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 276421
:
247741
|
247748
|
247749
|
247750
|
247769
|
247784
| 247874