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.
* Attempt a QEMU exit via the ISA debug exit device
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 <alejandro.garciavallejo@amd.com>
---
v3:
* Introduce cpu_has_xen. To be used in next patch to skip issuing a
hypercall when Xen ain't there.
---
arch/x86/include/arch/cpuid.h | 2 ++
arch/x86/setup.c | 55 +++++++++++++++++++++++++----------
2 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/arch/x86/include/arch/cpuid.h b/arch/x86/include/arch/cpuid.h
index 364b0b4..518aaf2 100644
--- a/arch/x86/include/arch/cpuid.h
+++ b/arch/x86/include/arch/cpuid.h
@@ -101,6 +101,8 @@ static inline bool cpu_has(unsigned int feature)
#define cpu_has_rtm_always_abort cpu_has(X86_FEATURE_RTM_ALWAYS_ABORT)
+extern bool cpu_has_xen;
+
#endif /* XTF_X86_CPUID_H */
/*
diff --git a/arch/x86/setup.c b/arch/x86/setup.c
index ba6f9c3..929d8aa 100644
--- a/arch/x86/setup.c
+++ b/arch/x86/setup.c
@@ -26,6 +26,7 @@ enum x86_vendor x86_vendor;
unsigned int max_leaf, max_extd_leaf;
unsigned int x86_family, x86_model, x86_stepping;
unsigned int maxphysaddr, maxvirtaddr;
+bool cpu_has_xen = IS_DEFINED(CONFIG_PV);
const char environment_description[] = ENVIRONMENT_DESCRIPTION;
@@ -102,12 +103,13 @@ static void collect_cpuid(cpuid_count_fn_t cpuid_fn)
* Find the Xen CPUID leaves. They may be at 0x4000_0000, or at 0x4000_0100
* if Xen is e.g. providing a viridian interface to the guest too.
*/
-static unsigned int find_xen_leaves(void)
+static unsigned int find_xen_leaves(bool assert_found)
{
+#define XEN_LEAVES_NOT_FOUND (-1U)
static unsigned int leaves;
if ( leaves )
- return leaves;
+ goto out;
for ( unsigned int l = XEN_CPUID_FIRST_LEAF;
l < XEN_CPUID_FIRST_LEAF + 0x10000; l += 0x100 )
@@ -122,11 +124,19 @@ static unsigned int find_xen_leaves(void)
((eax - l) >= 2) )
{
leaves = l;
+ cpu_has_xen = true;
+
return l;
}
}
- panic("Unable to locate Xen CPUID leaves\n");
+ leaves = XEN_LEAVES_NOT_FOUND;
+
+out:
+ if ( assert_found && (leaves == XEN_LEAVES_NOT_FOUND) )
+ panic("Unable to locate Xen CPUID leaves\n");
+
+ return leaves;
}
/*
@@ -140,7 +150,7 @@ static void init_hypercalls(void)
if ( IS_DEFINED(CONFIG_HVM) )
{
uint32_t eax, ebx, ecx, edx;
- unsigned int base = find_xen_leaves();
+ unsigned int base = find_xen_leaves(true);
cpuid(base + 2, &eax, &ebx, &ecx, &edx);
wrmsr(ebx, _u(hypercall_page));
@@ -248,6 +258,11 @@ static void qemu_console_write(const char *buf, size_t len)
rep_outsb(buf, len, 0x12);
}
+static void com1_console_write(const char *buf, size_t len)
+{
+ rep_outsb(buf, len, 0x3f8);
+}
+
static void xen_console_write(const char *buf, size_t len)
{
hypercall_console_write(buf, len);
@@ -255,10 +270,17 @@ static void xen_console_write(const char *buf, size_t len)
void arch_setup(void)
{
- if ( IS_DEFINED(CONFIG_HVM) && !pvh_start_info )
- register_console_callback(qemu_console_write);
+ find_xen_leaves(IS_DEFINED(CONFIG_PV));
+
+ if ( cpu_has_xen )
+ {
+ 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);
@@ -266,15 +288,18 @@ void arch_setup(void)
arch_init_traps();
- init_hypercalls();
-
- if ( !is_initdomain() )
+ if ( cpu_has_xen )
{
- 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)
@@ -282,7 +307,7 @@ int arch_get_domid(void)
if ( IS_DEFINED(CONFIG_HVM) )
{
uint32_t eax, ebx, ecx, edx;
- unsigned int base = find_xen_leaves();
+ unsigned int base = find_xen_leaves(true);
cpuid_count(base + 4, 0, &eax, &ebx, &ecx, &edx);
--
2.43.0
© 2016 - 2025 Red Hat, Inc.