Xen Test Framework
main.c
Go to the documentation of this file.
1
22#include <xtf.h>
23
24const char test_title[] = "Guest CPUID Faulting support";
25
26static unsigned long stub_cpuid(void)
27{
28 unsigned long fault = 0, tmp;
29
30 asm volatile("1: cpuid; 2:"
31 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
32 : "=a" (tmp), "+D" (fault)
33 : "a" (0), [rec] "p" (ex_record_fault_edi)
34 : "ebx", "ecx", "edx");
35
36 return fault;
37}
38
39static unsigned long stub_force_cpuid(void)
40{
41 unsigned long fault = 0, tmp;
42
43 asm volatile(_ASM_XEN_FEP
44 "1: cpuid; 2:"
45 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
46 : "=a" (tmp), "+D" (fault)
47 : "a" (0), [rec] "p" (ex_record_fault_edi)
48 : "ebx", "ecx", "edx");
49
50 return fault;
51}
52
53static unsigned long __user_text stub_user_cpuid(void)
54{
55 unsigned long fault = 0, tmp;
56
57 asm volatile("1: cpuid; 2:"
58 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
59 : "=a" (tmp), "+D" (fault)
60 : "a" (0), [rec] "p" (ex_record_fault_edi)
61 : "ebx", "ecx", "edx");
62
63 return fault;
64}
65
66static unsigned long __user_text stub_user_force_cpuid(void)
67{
68 unsigned long fault = 0, tmp;
69
70 asm volatile(_ASM_XEN_FEP
71 "1: cpuid; 2:"
72 _ASM_EXTABLE_HANDLER(1b, 2b, %P[rec])
73 : "=a" (tmp), "+D" (fault)
74 : "a" (0), [rec] "p" (ex_record_fault_edi)
75 : "ebx", "ecx", "edx");
76
77 return fault;
78}
79
80static void test_cpuid(bool exp_faulting)
81{
82 /*
83 * Kernel cpuids should never fault
84 */
85 if ( stub_cpuid() )
86 xtf_failure("Fail: kernel cpuid faulted\n");
87
88 if ( IS_DEFINED(CONFIG_PV) && stub_force_cpuid() )
89 xtf_failure("Fail: kernel pv cpuid faulted\n");
90
92 xtf_failure("Fail: kernel emulated cpuid faulted\n");
93
94 /*
95 * User cpuids should raise #GP[0] if faulting is enabled.
96 */
97 unsigned long exp = exp_faulting ? EXINFO_SYM(GP, 0) : 0;
98 const char *exp_fail_str = exp_faulting ? "didn't fault" : "faulted";
99
100 if ( exec_user(stub_user_cpuid) != exp )
101 xtf_failure("Fail: user cpuid %s\n", exp_fail_str);
102
103 if ( IS_DEFINED(CONFIG_PV) && exec_user(stub_user_force_cpuid) != exp )
104 xtf_failure("Fail: user pv cpuid %s\n", exp_fail_str);
105
107 xtf_failure("Fail: user emulated cpuid %s\n", exp_fail_str);
108}
109
110void test_main(void)
111{
112 uint64_t platform_info, features_enable;
113
114 if ( IS_DEFINED(CONFIG_HVM) && !xtf_has_fep )
115 xtf_skip("FEP support not detected - some tests will be skipped\n");
116
117 /* No faulting. CPUID should work without faulting anywhere. */
118 printk("Testing CPUID without faulting enabled\n");
119 test_cpuid(false);
120
121 /* Probe for CPUID Faulting support. */
122 if ( rdmsr_safe(MSR_INTEL_PLATFORM_INFO, &platform_info) ||
123 !(platform_info & PLATFORM_INFO_CPUID_FAULTING) )
124 return xtf_skip("Skip: CPUID Faulting unavailable\n");
125
126 if ( rdmsr_safe(MSR_INTEL_MISC_FEATURES_ENABLES, &features_enable) )
127 return xtf_error("Error: Fault accessing MISC_FEATURES_ENABLES\n");
128
129 /* Attempt to enable CPUID Faulting. */
131 features_enable | MISC_FEATURES_CPUID_FAULTING) )
132 return xtf_failure("Fail: Unable to enable CPUID Faulting\n");
133
134 /* Faulting active. CPUID should fault ouside of the kernel. */
135 printk("Testing CPUID with faulting enabled\n");
136 test_cpuid(true);
137
138 /* Try disabling faulting. */
139 if ( wrmsr_safe(MSR_INTEL_MISC_FEATURES_ENABLES, features_enable) )
140 return xtf_failure("Fail: Unable to disable CPUID Faulting\n");
141
142 /* Double check that CPUID no longer faults. */
143 printk("Retesting CPUID without faulting enabled\n");
144 test_cpuid(false);
145
147}
148
149/*
150 * Local variables:
151 * mode: C
152 * c-file-style: "BSD"
153 * c-basic-offset: 4
154 * tab-width: 4
155 * indent-tabs-mode: nil
156 * End:
157 */
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
bool ex_record_fault_edi(struct cpu_regs *regs, const struct extable_entry *ex)
Record the current fault in %edi.
Definition: extable.c:16
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use.
Definition: setup.c:276
#define __user_text
Definition: compiler.h:33
void printk(const char *fmt,...)
Definition: console.c:134
static unsigned long stub_user_force_cpuid(void)
Definition: main.c:66
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:110
const char test_title[]
The title of the test.
Definition: main.c:24
static unsigned long stub_cpuid(void)
Definition: main.c:26
static void test_cpuid(bool exp_faulting)
Definition: main.c:80
static unsigned long stub_force_cpuid(void)
Definition: main.c:39
static unsigned long stub_user_cpuid(void)
Definition: main.c:53
#define EXINFO_SYM(exc, ec)
Definition: exinfo.h:29
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
static unsigned long exec_user(unsigned long(*fn)(void))
Definition: lib.h:62
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define GP
#define MSR_INTEL_MISC_FEATURES_ENABLES
Definition: msr-index.h:23
#define MSR_INTEL_PLATFORM_INFO
Definition: msr-index.h:20
#define PLATFORM_INFO_CPUID_FAULTING
Definition: msr-index.h:21
#define MISC_FEATURES_CPUID_FAULTING
Definition: msr-index.h:24
static bool wrmsr_safe(uint32_t idx, uint64_t val)
Wrapper around wrmsr which safely catches #GP[0].
Definition: msr.h:69
static bool rdmsr_safe(uint32_t idx, uint64_t *val)
Wrapper around rdmsr which safely catches #GP[0].
Definition: msr.h:35
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define NULL
Definition: stddef.h:12
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17