git: 399386f190f1 - main - x86/xen: introduce non-hypercall based emergency print

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

URL: https://cgit.FreeBSD.org/src/commit/?id=399386f190f157073baaa56925e92cc90edded8c

commit 399386f190f157073baaa56925e92cc90edded8c
Author:     Roger Pau Monné <royger@FreeBSD.org>
AuthorDate: 2024-01-22 13:20:25 +0000
Commit:     Roger Pau Monné <royger@FreeBSD.org>
CommitDate: 2024-02-22 10:08:03 +0000

    x86/xen: introduce non-hypercall based emergency print
    
    The current xc_printf() function uses an hypercall in order to send character
    buffers to the hypervisor for it to print on the hypervisor console (if the
    hypervisor is configured to print such messages).
    
    This requires the hypercall page to be initialized, which is extra work and can
    go wrong.
    
    On x86 instead of using the console IO hypercall use the debug console IO port,
    also called "port E9 hack".  This allows sending characters to Xen using an
    outb instruction, without any initialization required.
    
    Keep the previous hypervisor based implementation by using the weak attribute,
    which allows each architecture to provide an alternate (arch-specific)
    implementation.
    
    Sponsored by: Cloud Software Group
    Reviewed by: markj
    Differential revision: https://reviews.freebsd.org/D43929
---
 sys/dev/xen/console/xen_console.c | 15 ++++++++++-----
 sys/x86/xen/hvm.c                 |  5 +++++
 sys/xen/xen-os.h                  |  7 +++++++
 3 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/sys/dev/xen/console/xen_console.c b/sys/dev/xen/console/xen_console.c
index d232dd4e0c1c..f1a298a2aefa 100644
--- a/sys/dev/xen/console/xen_console.c
+++ b/sys/dev/xen/console/xen_console.c
@@ -138,6 +138,13 @@ struct putchar_arg {
 	size_t	n_next;
 };
 
+void __weak_symbol
+xen_emergency_print(const char *str, size_t size)
+{
+	KASSERT((xen_domain()), ("call to xc_printf from non Xen guest"));
+	HYPERVISOR_console_write(str, size);
+}
+
 static void
 putchar(int c, void *arg)
 {
@@ -150,12 +157,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;
 		}
 	}
@@ -177,15 +184,13 @@ xc_printf(const char *fmt, ...)
 	pca.size = 0;
 #endif
 
-	KASSERT((xen_domain()), ("call to xc_printf from non Xen guest"));
-
 	va_start(ap, fmt);
 	kvprintf(fmt, putchar, &pca, 10, ap);
 	va_end(ap);
 
 #ifdef PRINTF_BUFR_SIZE
 	if (pca.n_next != 0)
-		HYPERVISOR_console_write(buf, pca.n_next);
+		xen_emergency_print(buf, pca.n_next);
 #endif
 }
 
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
index b8125e230b6f..6411b790a2be 100644
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -95,6 +95,11 @@ 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)
+{
+	outsb(XEN_HVM_DEBUGCONS_IOPORT, str, size);
+}
+
 uint32_t xen_cpuid_base;
 
 static uint32_t
diff --git a/sys/xen/xen-os.h b/sys/xen/xen-os.h
index d7e9b3ca8632..98be41124846 100644
--- a/sys/xen/xen-os.h
+++ b/sys/xen/xen-os.h
@@ -151,6 +151,13 @@ 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);
+
 #ifndef xen_mb
 #define xen_mb() mb()
 #endif