Xen Test Framework
setup.c
Go to the documentation of this file.
1#include <xtf/lib.h>
2#include <xtf/hypercall.h>
3#include <xtf/extable.h>
4#include <xtf/report.h>
5#include <xtf/xenbus.h>
6
7#include <arch/cpuid.h>
8#include <arch/desc.h>
9#include <arch/lib.h>
10#include <arch/mm.h>
11#include <arch/symbolic-const.h>
12#include <arch/traps.h>
13
14/*
15 * XTF Stack layout:
16 *
17 * boot_stack[page 3] Emergency entrypoint
18 * boot_stack[page 2] Exception entrypoints
19 * boot_stack[page 1] Top of work stack
20 */
23
26unsigned int max_leaf, max_extd_leaf;
29
30const char environment_description[] = ENVIRONMENT_DESCRIPTION;
31
33
34static void collect_cpuid(cpuid_count_fn_t cpuid_fn)
35{
36 unsigned int tmp, eax, ebx, ecx, edx, addr = 0;
37
38 cpuid_fn(0, 0, &max_leaf, &ebx, &ecx, &edx);
39
40 if ( ebx == 0x756e6547u && /* "GenuineIntel" */
41 ecx == 0x6c65746eu &&
42 edx == 0x49656e69u )
44
45 else if ( ebx == 0x68747541u && /* "AuthenticAMD" */
46 ecx == 0x444d4163u &&
47 edx == 0x69746e65u )
49
50 else
52
53 if ( max_leaf >= 1 )
54 {
55 cpuid_fn(1, 0, &eax, &tmp,
58
59 x86_stepping = (eax >> 0) & 0xf;
60 x86_model = (eax >> 4) & 0xf;
61 x86_family = (eax >> 8) & 0xf;
62
63 if ( (x86_family == 0xf) ||
65 x86_model |= ((eax >> 16) & 0xf) << 4;
66
67 if ( x86_family == 0xf )
68 x86_family += (eax >> 20) & 0xff;
69 }
70 if ( max_leaf >= 7 )
71 cpuid_fn(7, 0, &tmp,
75 if ( max_leaf >= 0xd )
76 cpuid_fn(0xd, 0,
78 &tmp, &tmp, &tmp);
79
80 cpuid_fn(0x80000000, 0, &max_extd_leaf, &tmp, &tmp, &tmp);
81
82 if ( (max_extd_leaf >> 16) == 0x8000 )
83 {
84 if ( max_extd_leaf >= 0x80000001 )
85 cpuid_fn(0x80000001, 0, &tmp, &tmp,
88 if ( max_extd_leaf >= 0x80000007 )
89 cpuid_fn(0x80000007, 0, &tmp, &tmp, &tmp,
91 if ( max_extd_leaf >= 0x80000008 )
92 cpuid_fn(0x80000008, 0, &addr,
94 &tmp, &tmp);
95 }
96
97 maxphysaddr = (addr & 0xff) ?: 36;
98 maxvirtaddr = ((addr >> 8) & 0xff) ?: 32;
99}
100
101/*
102 * PV guests should have hypercalls set up by the domain builder, due to the
103 * HYPERCALL_PAGE ELFNOTE being filled. HVM guests have to locate the
104 * hypervisor cpuid leaves to find correct MSR to requst that Xen writes a
105 * hypercall page.
106 */
107static void init_hypercalls(void)
108{
109 if ( IS_DEFINED(CONFIG_HVM) )
110 {
111 uint32_t eax, ebx, ecx, edx, base;
112 bool found = false;
113
114 for ( base = XEN_CPUID_FIRST_LEAF;
115 base < XEN_CPUID_FIRST_LEAF + 0x10000; base += 0x100 )
116 {
117 cpuid(base, &eax, &ebx, &ecx, &edx);
118
119 if ( (ebx == XEN_CPUID_SIGNATURE_EBX) &&
120 (ecx == XEN_CPUID_SIGNATURE_ECX) &&
121 (edx == XEN_CPUID_SIGNATURE_EDX) &&
122 ((eax - base) >= 2) )
123 {
124 found = true;
125 break;
126 }
127 }
128
129 if ( !found )
130 panic("Unable to locate Xen CPUID leaves\n");
131
132 cpuid(base + 2, &eax, &ebx, &ecx, &edx);
133 wrmsr(ebx, _u(hypercall_page));
134 barrier();
135 }
136
137 /*
138 * Confirm that the `ret` poision has been overwritten with a real
139 * hypercall page. At the time of writing, a legitimate hypercall page
140 * should start with `movl $0, %eax` or `0xb8 imm32`.
141 */
142 if ( hypercall_page[0] == 0xc3 )
143 panic("Hypercall page not initialised correctly\n");
144}
145
146static bool is_initdomain(void)
147{
148 if ( IS_DEFINED(CONFIG_PV) )
150 else
152}
153
154static void setup_pv_console(void)
155{
156 xencons_interface_t *cons_ring;
157 evtchn_port_t cons_evtchn;
158
159 if ( IS_DEFINED(CONFIG_PV) )
160 {
162 cons_evtchn = pv_start_info->console.domU.evtchn;
163 }
164 else /* HVM */
165 {
166 uint64_t raw_pfn, raw_evtchn;
167
168 if ( hvm_get_param(HVM_PARAM_CONSOLE_PFN, &raw_pfn) != 0 ||
169 hvm_get_param(HVM_PARAM_CONSOLE_EVTCHN, &raw_evtchn) != 0 )
170 return;
171
172 cons_ring = pfn_to_virt(raw_pfn);
173 cons_evtchn = raw_evtchn;
174 }
175
176 init_pv_console(cons_ring, cons_evtchn);
177}
178
179static void setup_xenbus(void)
180{
183
184 if ( IS_DEFINED(CONFIG_PV) )
185 {
188 }
189 else /* HVM */
190 {
191 uint64_t raw_pfn, raw_evtchn;
192 int rc;
193
194 rc = hvm_get_param(HVM_PARAM_STORE_PFN, &raw_pfn);
195 if ( rc )
196 panic("Failed to get XenStore PFN: %d\n", rc);
197
198 rc = hvm_get_param(HVM_PARAM_STORE_EVTCHN, &raw_evtchn);
199 if ( rc )
200 panic("Failed to get XenStore evtchn: %d\n", rc);
201
202 xb_ring = pfn_to_virt(raw_pfn);
203 xb_port = raw_evtchn;
204 }
205
207}
208
209static void map_shared_info(void)
210{
211 int rc;
212
213 if ( IS_DEFINED(CONFIG_HVM) )
214 {
215 struct xen_add_to_physmap xatp =
216 {
217 .domid = DOMID_SELF,
219 .idx = 0,
220 .gfn = virt_to_gfn(&shared_info),
221 };
222
224 }
225 else /* PV */
229
230 if ( rc )
231 panic("Failed to map shared_info: %d\n", rc);
232}
233
234static void qemu_console_write(const char *buf, size_t len)
235{
236 asm volatile("rep; outsb"
237 : "+S" (buf), "+c" (len)
238 : "d" (0x12));
239}
240
241static void xen_console_write(const char *buf, size_t len)
242{
243 hypercall_console_write(buf, len);
244}
245
246void arch_setup(void)
247{
248 if ( IS_DEFINED(CONFIG_HVM) && !pvh_start_info )
250
252
254
255 sort_extable();
256
258
260
261 if ( !is_initdomain() )
262 {
264 setup_xenbus();
265 }
266
268}
269
270/*
271 * Common test setup:
272 *
273 * xtf_has_* indicates the availabiliy of options which require runtime
274 * detection.
275 */
276bool xtf_has_fep = false;
277
278/*
279 * Default weak settings.
280 *
281 * test_wants_* indicates default settings for the framework, which may be
282 * overridden by individual tests by providing non-weak variables.
283 *
284 * test_needs_* indicates options required by the test, without which the test
285 * isn't worth running.
286 */
288
289void test_setup(void)
290{
291 /*
292 * Attempt to use the forced emulation prefix to set the value of
293 * xtf_has_fep to the value of 1. Use the exception table to compensate
294 * for the #UD exception if FEP is not available.
295 */
296 asm volatile ("1:" _ASM_XEN_FEP "mov $1, %[fep];"
297 "2:"
298 _ASM_EXTABLE(1b, 2b)
299 : [fep] "=q" (xtf_has_fep)
300 : "0" (false));
301
302 if ( test_needs_fep && !xtf_has_fep )
303 {
304 printk("FEP unavailable, but needed by test. (Is Xen support\n");
305 return xtf_skip("compiled in, and booted with 'hvm_fep'?)\n");
306 }
307}
308
309/*
310 * Local variables:
311 * mode: C
312 * c-file-style: "BSD"
313 * c-basic-offset: 4
314 * tab-width: 4
315 * indent-tabs-mode: nil
316 * End:
317 */
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
void(* cpuid_count_fn_t)(uint32_t leaf, uint32_t subleaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Definition: cpuid.h:12
#define FEATURESET_e8b
Definition: cpuid.h:49
#define FEATURESET_e1d
Definition: cpuid.h:43
#define FEATURESET_1c
Definition: cpuid.h:42
#define FEATURESET_e1c
Definition: cpuid.h:44
#define FEATURESET_7c0
Definition: cpuid.h:47
#define FEATURESET_1d
Definition: cpuid.h:41
#define FEATURESET_e7d
Definition: cpuid.h:48
x86_vendor
Definition: cpuid.h:17
@ X86_VENDOR_AMD
Definition: cpuid.h:20
@ X86_VENDOR_INTEL
Definition: cpuid.h:19
@ X86_VENDOR_UNKNOWN
Definition: cpuid.h:18
#define FEATURESET_7d0
Definition: cpuid.h:50
#define FEATURESET_7b0
Definition: cpuid.h:46
#define FSCAPINTS
Definition: cpuid.h:52
#define FEATURESET_Da1
Definition: cpuid.h:45
static void cpuid_count(uint32_t leaf, uint32_t subleaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Definition: lib.h:64
static void pv_cpuid_count(uint32_t leaf, uint32_t subleaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Definition: lib.h:73
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Definition: lib.h:10
xen_pv_start_info_t * pv_start_info
Definition: traps.c:14
unsigned int x86_family
Definition: setup.c:27
static void map_shared_info(void)
Definition: setup.c:209
static void qemu_console_write(const char *buf, size_t len)
Definition: setup.c:234
static void xen_console_write(const char *buf, size_t len)
Definition: setup.c:241
static void collect_cpuid(cpuid_count_fn_t cpuid_fn)
Definition: setup.c:34
unsigned int max_leaf
Definition: setup.c:26
uint32_t x86_features[FSCAPINTS]
Definition: setup.c:24
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use.
Definition: setup.c:276
static void setup_pv_console(void)
Definition: setup.c:154
uint8_t user_stack[PAGE_SIZE]
Definition: setup.c:22
unsigned int x86_stepping
Definition: setup.c:27
const char environment_description[]
Definition: setup.c:30
void test_setup(void)
Definition: setup.c:289
void arch_setup(void)
Definition: setup.c:246
static bool is_initdomain(void)
Definition: setup.c:146
unsigned int x86_model
Definition: setup.c:27
unsigned int maxvirtaddr
Definition: setup.c:28
static void setup_xenbus(void)
Definition: setup.c:179
enum x86_vendor x86_vendor
Definition: setup.c:25
uint8_t boot_stack[3 *PAGE_SIZE]
Definition: setup.c:21
static void init_hypercalls(void)
Definition: setup.c:107
unsigned int maxphysaddr
Definition: setup.c:28
unsigned int max_extd_leaf
Definition: setup.c:26
bool test_needs_fep
Boolean indicating whether the test is entirely predicated on the available of the Force Emulation Pr...
Definition: setup.c:287
void sort_extable(void)
Sort the exception table.
Definition: extable.c:52
#define __weak
Definition: compiler.h:15
#define barrier()
Definition: compiler.h:30
#define __page_aligned_bss
Definition: compiler.h:37
#define __user_page_aligned_bss
Definition: compiler.h:39
void printk(const char *fmt,...)
Definition: console.c:134
void register_console_callback(cons_output_cb fn)
Definition: console.c:24
void init_pv_console(xencons_interface_t *ring, evtchn_port_t port)
Definition: console.c:109
x86 segment descriptor infrastructure.
uint32_t evtchn_port_t
Definition: event_channel.h:11
void arch_init_traps(void)
Definition: traps.c:86
xen_pvh_start_info_t * pvh_start_info
Definition: traps.c:11
static int hvm_get_param(unsigned int idx, uint64_t *value)
Definition: hypercall.h:235
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
static void hypercall_console_write(const char *buf, unsigned long count)
Definition: hypercall.h:196
static long hypercall_memory_op(unsigned int cmd, void *arg)
Definition: hypercall.h:100
uint8_t hypercall_page[PAGE_SIZE]
#define XEN_CPUID_SIGNATURE_ECX
Definition: cpuid.h:27
#define XEN_CPUID_SIGNATURE_EBX
Definition: cpuid.h:26
#define XEN_CPUID_SIGNATURE_EDX
Definition: cpuid.h:28
#define XEN_CPUID_FIRST_LEAF
Definition: cpuid.h:17
Exception table support.
#define _ASM_EXTABLE(fault, fixup)
Create an exception table entry.
Definition: extable.h:50
void panic(const char *fmt,...)
Definition: lib.c:15
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define XENMEM_add_to_physmap
Definition: memory.h:22
#define XENMAPSPACE_shared_info
Definition: memory.h:28
void * mfn_to_virt(unsigned long mfn)
static void * pfn_to_virt(unsigned long pfn)
Definition: mm.h:37
static unsigned long virt_to_gfn(const void *va)
Definition: mm.h:100
static void wrmsr(uint32_t idx, uint64_t val)
Thin wrapper around an wrmsr instruction.
Definition: msr.h:55
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define PAGE_SIZE
Definition: page.h:11
#define HVM_PARAM_CONSOLE_EVTCHN
Definition: params.h:12
#define HVM_PARAM_STORE_EVTCHN
Definition: params.h:9
#define HVM_PARAM_CONSOLE_PFN
Definition: params.h:11
#define HVM_PARAM_STORE_PFN
Definition: params.h:8
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
API for reporting test status.
__UINT32_TYPE__ uint32_t
Definition: stdint.h:16
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
domid_t domid
Definition: memory.h:25
xen_pfn_t store_mfn
Definition: xen.h:210
struct xen_pv_start_info::@48::@49 domU
xen_pfn_t mfn
Definition: xen.h:214
uint32_t flags
Definition: xen.h:209
unsigned long shared_info
Definition: xen.h:208
union xen_pv_start_info::@48 console
uint32_t evtchn
Definition: xen.h:215
uint32_t store_evtchn
Definition: xen.h:211
Macros for creating constants using mnemonics.
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define DOMID_SELF
Definition: xen.h:70
#define SIF_INITDOMAIN
Definition: xen.h:241
@ UVMF_INVLPG
Definition: xen.h:383
void init_xenbus(xenbus_interface_t *ring, evtchn_port_t port)
Definition: xenbus.c:12
static xenbus_interface_t * xb_ring
Definition: xenbus.c:8
static evtchn_port_t xb_port
Definition: xenbus.c:9