xref: /linux/arch/x86/kernel/cpu/bhyve.c (revision a65879b4584f98e6c1b80380f55ca8cfca82cb47)
1*fa1d1171SDavid Woodhouse // SPDX-License-Identifier: GPL-2.0
2*fa1d1171SDavid Woodhouse /*
3*fa1d1171SDavid Woodhouse  * FreeBSD Bhyve guest enlightenments
4*fa1d1171SDavid Woodhouse  *
5*fa1d1171SDavid Woodhouse  * Copyright © 2025 Amazon.com, Inc. or its affiliates.
6*fa1d1171SDavid Woodhouse  *
7*fa1d1171SDavid Woodhouse  * Author: David Woodhouse <dwmw2@infradead.org>
8*fa1d1171SDavid Woodhouse  */
9*fa1d1171SDavid Woodhouse 
10*fa1d1171SDavid Woodhouse #include <linux/init.h>
11*fa1d1171SDavid Woodhouse #include <linux/export.h>
12*fa1d1171SDavid Woodhouse #include <asm/processor.h>
13*fa1d1171SDavid Woodhouse #include <asm/hypervisor.h>
14*fa1d1171SDavid Woodhouse 
15*fa1d1171SDavid Woodhouse static uint32_t bhyve_cpuid_base;
16*fa1d1171SDavid Woodhouse static uint32_t bhyve_cpuid_max;
17*fa1d1171SDavid Woodhouse 
18*fa1d1171SDavid Woodhouse #define BHYVE_SIGNATURE			"bhyve bhyve "
19*fa1d1171SDavid Woodhouse 
20*fa1d1171SDavid Woodhouse #define CPUID_BHYVE_FEATURES		0x40000001
21*fa1d1171SDavid Woodhouse 
22*fa1d1171SDavid Woodhouse /* Features advertised in CPUID_BHYVE_FEATURES %eax */
23*fa1d1171SDavid Woodhouse 
24*fa1d1171SDavid Woodhouse /* MSI Extended Dest ID */
25*fa1d1171SDavid Woodhouse #define CPUID_BHYVE_FEAT_EXT_DEST_ID	(1UL << 0)
26*fa1d1171SDavid Woodhouse 
bhyve_detect(void)27*fa1d1171SDavid Woodhouse static uint32_t __init bhyve_detect(void)
28*fa1d1171SDavid Woodhouse {
29*fa1d1171SDavid Woodhouse 	if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
30*fa1d1171SDavid Woodhouse                 return 0;
31*fa1d1171SDavid Woodhouse 
32*fa1d1171SDavid Woodhouse 	bhyve_cpuid_base = cpuid_base_hypervisor(BHYVE_SIGNATURE, 0);
33*fa1d1171SDavid Woodhouse 	if (!bhyve_cpuid_base)
34*fa1d1171SDavid Woodhouse 		return 0;
35*fa1d1171SDavid Woodhouse 
36*fa1d1171SDavid Woodhouse 	bhyve_cpuid_max = cpuid_eax(bhyve_cpuid_base);
37*fa1d1171SDavid Woodhouse 	return bhyve_cpuid_max;
38*fa1d1171SDavid Woodhouse }
39*fa1d1171SDavid Woodhouse 
bhyve_features(void)40*fa1d1171SDavid Woodhouse static uint32_t bhyve_features(void)
41*fa1d1171SDavid Woodhouse {
42*fa1d1171SDavid Woodhouse 	unsigned int cpuid_leaf = bhyve_cpuid_base | CPUID_BHYVE_FEATURES;
43*fa1d1171SDavid Woodhouse 
44*fa1d1171SDavid Woodhouse 	if (bhyve_cpuid_max < cpuid_leaf)
45*fa1d1171SDavid Woodhouse 		return 0;
46*fa1d1171SDavid Woodhouse 
47*fa1d1171SDavid Woodhouse 	return cpuid_eax(cpuid_leaf);
48*fa1d1171SDavid Woodhouse }
49*fa1d1171SDavid Woodhouse 
bhyve_ext_dest_id(void)50*fa1d1171SDavid Woodhouse static bool __init bhyve_ext_dest_id(void)
51*fa1d1171SDavid Woodhouse {
52*fa1d1171SDavid Woodhouse 	return !!(bhyve_features() & CPUID_BHYVE_FEAT_EXT_DEST_ID);
53*fa1d1171SDavid Woodhouse }
54*fa1d1171SDavid Woodhouse 
bhyve_x2apic_available(void)55*fa1d1171SDavid Woodhouse static bool __init bhyve_x2apic_available(void)
56*fa1d1171SDavid Woodhouse {
57*fa1d1171SDavid Woodhouse 	return true;
58*fa1d1171SDavid Woodhouse }
59*fa1d1171SDavid Woodhouse 
60*fa1d1171SDavid Woodhouse const struct hypervisor_x86 x86_hyper_bhyve __refconst = {
61*fa1d1171SDavid Woodhouse 	.name			= "Bhyve",
62*fa1d1171SDavid Woodhouse 	.detect			= bhyve_detect,
63*fa1d1171SDavid Woodhouse 	.init.init_platform	= x86_init_noop,
64*fa1d1171SDavid Woodhouse 	.init.x2apic_available	= bhyve_x2apic_available,
65*fa1d1171SDavid Woodhouse 	.init.msi_ext_dest_id	= bhyve_ext_dest_id,
66*fa1d1171SDavid Woodhouse };
67