If Xen isn't detected on CPUID, then:

 * Skip setting up Xenbus/PV-console/shared_info/hypercalls/qemu-debug.
 * Register COM1 as an output callback.

This patch enables running XTF on QEMU-TCG/KVM out of the box. And a
minor tweaks to set up baud rate make it work on real hardware too.

Signed-off-by: Alejandro Vallejo <[email protected]>
---
I tested PV and HVM still run fine under Xen, and I did account for
viridian-enlightened guests, though I didn't test them.

---
 arch/x86/setup.c | 68 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 55 insertions(+), 13 deletions(-)

diff --git a/arch/x86/setup.c b/arch/x86/setup.c
index 2ac212e..6172c7e 100644
--- a/arch/x86/setup.c
+++ b/arch/x86/setup.c
@@ -31,6 +31,8 @@ const char environment_description[] = 
ENVIRONMENT_DESCRIPTION;
 
 shared_info_t shared_info __page_aligned_bss;
 
+static bool has_xen_hypervisor;
+
 static void collect_cpuid(cpuid_count_fn_t cpuid_fn)
 {
     unsigned int tmp, eax, ebx, ecx, edx, addr = 0;
@@ -243,11 +245,19 @@ static void map_shared_info(void)
         panic("Failed to map shared_info: %d\n", rc);
 }
 
+static void pio_write(uint16_t port, const char *buf, size_t len)
+{
+    asm volatile("rep; outsb" : "+S" (buf), "+c" (len) : "d" (port));
+}
+
 static void qemu_console_write(const char *buf, size_t len)
 {
-    asm volatile("rep outsb"
-                 : "+S" (buf), "+c" (len)
-                 : "d" (0x12));
+    pio_write(0x12, buf, len);
+}
+
+static void com1_console_write(const char *buf, size_t len)
+{
+    pio_write(0x3f8, buf, len);
 }
 
 static void xen_console_write(const char *buf, size_t len)
@@ -255,12 +265,41 @@ static void xen_console_write(const char *buf, size_t len)
     hypercall_console_write(buf, len);
 }
 
+static bool detect_xen_runtime(void)
+{
+    uint32_t eax, ebx, ecx, edx;
+
+    /* PV tests always run under Xen */
+    if ( IS_DEFINED(CONFIG_PV) )
+        return true;
+
+    /* HVM tests may additionally run on non-Xen hypervisors or baremetal */
+    cpuid_count(0x40000000, 0, &eax, &ebx, &ecx, &edx);
+    if (  ebx == XEN_CPUID_SIGNATURE_EBX &&
+          ecx == XEN_CPUID_SIGNATURE_ECX &&
+          edx == XEN_CPUID_SIGNATURE_EDX )
+        return true;
+
+    /* Viridian guests have the Xen leaves higher up, so check there too */
+    cpuid_count(0x40000100, 0, &eax, &ebx, &ecx, &edx);
+    return ebx == XEN_CPUID_SIGNATURE_EBX &&
+           ecx == XEN_CPUID_SIGNATURE_ECX &&
+           edx == XEN_CPUID_SIGNATURE_EDX;
+}
+
 void arch_setup(void)
 {
-    if ( IS_DEFINED(CONFIG_HVM) && !pvh_start_info )
-        register_console_callback(qemu_console_write);
+    has_xen_hypervisor = detect_xen_runtime();
+
+    if ( has_xen_hypervisor )
+    {
+        if ( IS_DEFINED(CONFIG_HVM) && !pvh_start_info )
+            register_console_callback(qemu_console_write);
 
-    register_console_callback(xen_console_write);
+        register_console_callback(xen_console_write);
+    }
+    else
+        register_console_callback(com1_console_write);
 
     collect_cpuid(IS_DEFINED(CONFIG_PV) ? pv_cpuid_count : cpuid_count);
 
@@ -268,15 +307,18 @@ void arch_setup(void)
 
     arch_init_traps();
 
-    init_hypercalls();
-
-    if ( !is_initdomain() )
+    if ( has_xen_hypervisor )
     {
-        setup_pv_console();
-        setup_xenbus();
-    }
+        init_hypercalls();
 
-    map_shared_info();
+        if ( !is_initdomain() )
+        {
+            setup_pv_console();
+            setup_xenbus();
+        }
+
+        map_shared_info();
+    }
 }
 
 int arch_get_domid(void)

base-commit: 0cbf4c35b06b2b285fc325b8458132e844c5cf0e
-- 
2.43.0


Reply via email to