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 
26 unsigned int max_leaf, max_extd_leaf;
28 unsigned int maxphysaddr, maxvirtaddr;
29 
30 const char environment_description[] = ENVIRONMENT_DESCRIPTION;
31 
33 
34 static 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) ||
64  (x86_vendor == X86_VENDOR_INTEL && x86_family == 0x6) )
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,
74  &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  */
107 static 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 
146 static bool is_initdomain(void)
147 {
148  if ( IS_DEFINED(CONFIG_PV) )
150  else
152 }
153 
154 static 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  {
161  cons_ring = mfn_to_virt(pv_start_info->console.domU.mfn);
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 
179 static void setup_xenbus(void)
180 {
183 
184  if ( IS_DEFINED(CONFIG_PV) )
185  {
186  xb_ring = mfn_to_virt(pv_start_info->store_mfn);
187  xb_port = pv_start_info->store_evtchn;
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 
206  init_xenbus(xb_ring, xb_port);
207 }
208 
209 static 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,
218  .space = XENMAPSPACE_shared_info,
219  .idx = 0,
220  .gfn = virt_to_gfn(&shared_info),
221  };
222 
224  }
225  else /* PV */
228  UVMF_INVLPG);
229 
230  if ( rc )
231  panic("Failed to map shared_info: %d\n", rc);
232 }
233 
234 static 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 
241 static void xen_console_write(const char *buf, size_t len)
242 {
243  hypercall_console_write(buf, len);
244 }
245 
246 void arch_setup(void)
247 {
248  if ( IS_DEFINED(CONFIG_HVM) && !pvh_start_info )
250 
252 
254 
255  sort_extable();
256 
257  arch_init_traps();
258 
259  init_hypercalls();
260 
261  if ( !is_initdomain() )
262  {
264  setup_xenbus();
265  }
266 
267  map_shared_info();
268 }
269 
270 /*
271  * Common test setup:
272  *
273  * xtf_has_* indicates the availabiliy of options which require runtime
274  * detection.
275  */
276 bool 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  */
287 bool __weak test_needs_fep = false;
288 
289 void 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  */
uint8_t boot_stack[3 *PAGE_SIZE]
Definition: setup.c:21
xen_pvh_start_info_t * pvh_start_info
Definition: traps.c:11
void init_pv_console(xencons_interface_t *ring, evtchn_port_t port)
Definition: console.c:109
static void wrmsr(uint32_t idx, uint64_t val)
Thin wrapper around an wrmsr instruction.
Definition: msr.h:55
static void setup_pv_console(void)
Definition: setup.c:154
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
void * mfn_to_virt(unsigned long mfn)
static void init_hypercalls(void)
Definition: setup.c:107
static evtchn_port_t xb_port
Definition: xenbus.c:9
uint32_t ecx
Definition: x86-tss.h:29
#define XEN_CPUID_SIGNATURE_EBX
Definition: cpuid.h:26
void sort_extable(void)
Sort the exception table.
Definition: extable.c:52
domid_t domid
Definition: memory.h:23
xen_pfn_t store_mfn
Definition: xen.h:210
uint32_t x86_features[FSCAPINTS]
Definition: setup.c:24
static void collect_cpuid(cpuid_count_fn_t cpuid_fn)
Definition: setup.c:34
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
Macros for creating constants using mnemonics.
#define FEATURESET_7c0
Definition: cpuid.h:47
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
Exception table support.
static void setup_xenbus(void)
Definition: setup.c:179
#define FEATURESET_Da1
Definition: cpuid.h:45
x86 segment descriptor infrastructure.
#define __page_aligned_bss
Definition: compiler.h:37
#define HVM_PARAM_CONSOLE_PFN
Definition: params.h:11
unsigned int max_leaf
Definition: setup.c:26
#define FEATURESET_e7d
Definition: cpuid.h:48
static xenbus_interface_t * xb_ring
Definition: xenbus.c:8
#define XEN_CPUID_FIRST_LEAF
Definition: cpuid.h:17
uint32_t evtchn_port_t
Definition: event_channel.h:11
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
uint32_t store_evtchn
Definition: xen.h:211
#define barrier()
Definition: compiler.h:30
void panic(const char *fmt,...)
Definition: lib.c:15
uint32_t eax
Definition: x86-tss.h:28
enum x86_vendor x86_vendor
Definition: setup.c:25
unsigned int maxvirtaddr
Definition: setup.c:28
uint8_t user_stack[PAGE_SIZE]
Definition: setup.c:22
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
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
unsigned long shared_info
Definition: xen.h:208
void printk(const char *fmt,...)
Definition: console.c:134
bool test_needs_fep
Boolean indicating whether the test is entirely predicated on the available of the Force Emulation Pr...
Definition: setup.c:287
bool xtf_has_fep
Boolean indicating whether generic Force Emulation Prefix support is available for the test to use...
Definition: setup.c:276
void register_console_callback(cons_output_cb fn)
Definition: console.c:24
static void * pfn_to_virt(unsigned long pfn)
Definition: mm.h:37
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define FEATURESET_e1d
Definition: cpuid.h:43
static void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Definition: lib.h:10
void init_xenbus(xenbus_interface_t *ring, evtchn_port_t port)
Definition: xenbus.c:12
#define XENMEM_add_to_physmap
Definition: memory.h:20
#define FEATURESET_e8b
Definition: cpuid.h:49
void arch_setup(void)
Definition: setup.c:246
uint8_t hypercall_page[PAGE_SIZE]
void test_setup(void)
Definition: setup.c:289
#define SIF_INITDOMAIN
Definition: xen.h:241
x86_vendor
Definition: cpuid.h:16
#define FEATURESET_7b0
Definition: cpuid.h:46
void arch_init_traps(void)
Definition: traps.c:86
unsigned int x86_stepping
Definition: setup.c:27
#define FEATURESET_1d
Definition: cpuid.h:41
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
static int hvm_get_param(unsigned int idx, uint64_t *value)
Definition: hypercall.h:235
static unsigned long virt_to_gfn(const void *va)
Definition: mm.h:100
#define XEN_CPUID_SIGNATURE_ECX
Definition: cpuid.h:27
#define HVM_PARAM_STORE_EVTCHN
Definition: params.h:9
void xtf_skip(const char *fmt,...)
Report a test skip.
Definition: report.c:66
const char environment_description[]
Definition: setup.c:30
__UINT32_TYPE__ uint32_t
Definition: stdint.h:16
#define FEATURESET_e1c
Definition: cpuid.h:44
#define XEN_CPUID_SIGNATURE_EDX
Definition: cpuid.h:28
unsigned int x86_family
Definition: setup.c:27
static void xen_console_write(const char *buf, size_t len)
Definition: setup.c:241
#define XENMAPSPACE_shared_info
Definition: memory.h:26
static bool is_initdomain(void)
Definition: setup.c:146
static void hypercall_console_write(const char *buf, unsigned long count)
Definition: hypercall.h:196
union xen_pv_start_info::@48 console
unsigned int max_extd_leaf
Definition: setup.c:26
struct xen_pv_start_info::@48::@49 domU
unsigned int maxphysaddr
Definition: setup.c:28
#define PAGE_SIZE
Definition: page.h:11
uint32_t edx
Definition: x86-tss.h:30
#define HVM_PARAM_STORE_PFN
Definition: params.h:8
#define FEATURESET_1c
Definition: cpuid.h:42
static void map_shared_info(void)
Definition: setup.c:209
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
xen_pv_start_info_t * pv_start_info
Definition: traps.c:14
#define _ASM_EXTABLE(fault, fixup)
Create an exception table entry.
Definition: extable.h:50
uint32_t ebx
Definition: x86-tss.h:31
#define __user_page_aligned_bss
Definition: compiler.h:39
#define DOMID_SELF
Definition: xen.h:70
static void qemu_console_write(const char *buf, size_t len)
Definition: setup.c:234
static long hypercall_memory_op(unsigned int cmd, void *arg)
Definition: hypercall.h:100
uint32_t flags
Definition: xen.h:209
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
#define HVM_PARAM_CONSOLE_EVTCHN
Definition: params.h:12
unsigned int x86_model
Definition: setup.c:27
#define FSCAPINTS
Definition: cpuid.h:51
#define __weak
Definition: compiler.h:15
API for reporting test status.