1111#include <asm/msr.h>
1212#include <asm/processor.h>
1313
14+ // -----------------------------------------------------------------------------
15+ // Prototypes
16+ // -----------------------------------------------------------------------------
17+
18+ void
19+ _mv_cpuid (
20+ uint32_t * eax ,
21+ uint32_t * ebx ,
22+ uint32_t * ecx ,
23+ uint32_t * edx );
24+
25+ // -----------------------------------------------------------------------------
26+ // Scalar Types
27+ // -----------------------------------------------------------------------------
28+
29+ #define mv_status_t uint64_t
30+ #define mv_uint8_t uint8_t
31+ #define mv_uint16_t uint16_t
32+ #define mv_uint32_t uint32_t
33+ #define mv_uint64_t uint64_t
34+
35+ // -----------------------------------------------------------------------------
36+ // Specification IDs
37+ // -----------------------------------------------------------------------------
38+
39+ #define MV_SPEC_ID1_VAL ((mv_uint32_t)0x3123764D)
40+
41+ // -----------------------------------------------------------------------------
42+ // Hypervisor Discovery
43+ // -----------------------------------------------------------------------------
44+
45+ #define MV_CPUID_HYPERVISOR_PRESENT (((mv_uint32_t)1) << 31)
46+ #define MV_CPUID_SPEC_ID1 (((mv_uint32_t)1) << 0)
47+
48+ #define MV_CPUID_MIN_LEAF_VAL ((mv_uint32_t)0x40000202)
49+ #define MV_CPUID_MAX_LEAF_VAL ((mv_uint32_t)0x4000FFFF)
50+ #define MV_CPUID_INIT_VAL ((mv_uint32_t)0x40000200)
51+ #define MV_CPUID_INC_VAL ((mv_uint32_t)0x100)
52+ #define MV_CPUID_VENDOR_ID1_VAL ((mv_uint32_t)0x694D6642)
53+ #define MV_CPUID_VENDOR_ID2_VAL ((mv_uint32_t)0x566F7263)
54+
55+ static inline mv_uint32_t
56+ mv_present (mv_uint32_t spec_id )
57+ {
58+ mv_uint32_t eax ;
59+ mv_uint32_t ebx ;
60+ mv_uint32_t ecx ;
61+ mv_uint32_t edx ;
62+ mv_uint32_t max_leaf ;
63+ mv_uint32_t leaf ;
64+
65+ /**
66+ * First check to see if software is running on a hypervisor. Although not
67+ * officially documented by Intel/AMD, bit 31 of the feature identifiers is
68+ * reserved for hypervisors, and any hypervisor that conforms (at least in
69+ * part) to the Hypervisor Top Level Functional Specification will set this.
70+ */
71+
72+ eax = 0x00000001 ;
73+ _mv_cpuid (& eax , & ebx , & ecx , & edx );
74+
75+ if ((ecx & MV_CPUID_HYPERVISOR_PRESENT ) == 0 ) {
76+ return 0 ;
77+ }
78+
79+ /**
80+ * Now that we know that we are running on a hypervisor, the next step is
81+ * determine how many hypervisor specific CPUID leaves are supported. This
82+ * is done as follows. Note that the MicroV spec defines the min/max values
83+ * for the return of this query, which we can also use to determine if this
84+ * is MicroV.
85+ */
86+
87+ eax = 0x40000000 ;
88+ _mv_cpuid (& eax , & ebx , & ecx , & edx );
89+
90+ max_leaf = eax ;
91+ if (max_leaf < MV_CPUID_MIN_LEAF_VAL || max_leaf > MV_CPUID_MAX_LEAF_VAL ) {
92+ return 0 ;
93+ }
94+
95+ /**
96+ * Now that we know how many CPUID leaves to parse, we can scan the CPUID
97+ * leaves for MicroV. Since MicroV also supports the HyperV and Xen
98+ * interfaces, we start at 0x40000200, and increment by 0x100 until we
99+ * find MicroV's signature. Normally, the first leaf should be MicroV, but
100+ * we need to scan just incase future MicroV specs add additional ABIs.
101+ */
102+
103+ for (leaf = MV_CPUID_INIT_VAL ; leaf < max_leaf ; leaf += MV_CPUID_INC_VAL ) {
104+ eax = leaf ;
105+ _mv_cpuid (& eax , & ebx , & ecx , & edx );
106+
107+ if (ebx == MV_CPUID_VENDOR_ID1_VAL && ecx == MV_CPUID_VENDOR_ID2_VAL ) {
108+ break ;
109+ }
110+ }
111+
112+ if (leaf >= max_leaf ) {
113+ return 0 ;
114+ }
115+
116+ /**
117+ * Finally, we need to verify which version of the spec software speaks and
118+ * verifying that MicroV also speaks this same spec.
119+ */
120+
121+ eax = leaf + 0x00000001U ;
122+ _mv_cpuid (& eax , & ebx , & ecx , & edx );
123+
124+ switch (spec_id ) {
125+ case MV_SPEC_ID1_VAL : {
126+ if ((eax & MV_CPUID_SPEC_ID1 ) == 0 ) {
127+ return 0 ;
128+ }
129+
130+ break ;
131+ }
132+
133+ default :
134+ return 0 ;
135+ }
136+
137+ /**
138+ * If we got this far, it means that software is running on MicroV, and
139+ * both MicroV and software speak the same specification, which means
140+ * software may proceed with communicating with MicroV. The next step is
141+ * to open an handle and use it for additional hypercalls.
142+ */
143+
144+ return 1 ;
145+ }
146+
147+ /* -------------------------------------------------------------------------- */
148+ /* !!! WARNING DEPRECATED !!! */
149+ /* -------------------------------------------------------------------------- */
150+
14151#define SUCCESS 0
15152#define FAILURE 0xFFFFFFFFFFFFFFFF
16153#define SUSPEND 0xFFFFFFFFFFFFFFFE
@@ -27,13 +164,6 @@ uint64_t asm_vmcall2(void *r1, void *r2);
27164uint64_t asm_vmcall3 (void * r1 , void * r2 , void * r3 );
28165uint64_t asm_vmcall4 (void * r1 , void * r2 , void * r3 , void * r4 );
29166
30- /* -------------------------------------------------------------------------- */
31- /* CPUID */
32- /* -------------------------------------------------------------------------- */
33-
34- #define CPUID_BAREFLANK_SYN 0x4BF00000
35- #define CPUID_BAREFLANK_ACK 0x4BF00001
36-
37167/* -------------------------------------------------------------------------- */
38168/* Virtual IRQs */
39169/* -------------------------------------------------------------------------- */
0 commit comments