Xen Test Framework
main.c
Go to the documentation of this file.
1
33#include <xtf.h>
34
35const char test_title[] = "XSA-186 PoC";
36
37bool test_needs_fep = true;
38
39/* Test-local `int` handler. */
41asm(".align 16;"
42 "test_int_handler:"
43 "movl $0xc0de, %eax;"
44 __ASM_SEL(iretl, iretq)
45 );
46
47static const struct xtf_idte idte = {
49 .cs = __KERN_CS,
50};
51
52/* Stub instruction buffer. */
53asm(".align 16;"
54 "insn_stub_start:;"
56 ".Lstub_fault:;"
57 ".byte 0x67; int $" STR(X86_VEC_AVAIL) ";"
58 ".Lstub_fixup: ret;"
59 "insn_stub_end:;"
60 );
61
62static bool ex_fault(struct cpu_regs *regs, const struct extable_entry *ex)
63{
64 if ( regs->entry_vector == X86_EXC_GP && regs->error_code == 0 )
65 {
66 extern char _fault[] asm(".Lstub_fault");
67 extern char _fixup[] asm(".Lstub_fixup");
68 const size_t delta = _fixup - _fault;
69
70 regs->ax = 0xc0de;
71 regs->ip += delta;
72 return true;
73 }
74
75 return false;
76}
77
78void test_main(void)
79{
80 /* Hook test_int_handler() into the real IDT. */
82
83 /* Reinstate the mapping at 0 virtual. It will be needed. */
84 if ( CONFIG_PAGING_LEVELS > 0 )
85 {
86 l1_identmap[0] = pte_from_gfn(0, PF_SYM(AD, RW, P));
87 barrier();
88 }
89
90 if ( IS_DEFINED(CONFIG_64BIT) )
91 {
94
95 /*
96 * The manuals say we can't `iretq` to a compat mode code segment with
97 * a NULL %ss. Indeed, this causes a #GP(0). Despite the fact we can
98 * `lcall/lret` ourselves there, and everything works fine.
99 *
100 * /sigh x86...
101 *
102 * Load a flat non-NULL %ss so test_int_handler() can sensibly return.
103 */
105
106 /* Map gfn 0 at the very top of virtual address space. */
107 nl1t[511] = pte_from_gfn(0, PF_SYM(AD, RW, P));
108 nl2t[511] = pte_from_virt(nl1t, PF_SYM(AD, U, RW, P));
109 pae_l3_identmap[511] = pte_from_virt(nl2t, PF_SYM(AD, U, RW, P));
110 pae_l4_identmap[511] = pte_from_virt(pae_l3_identmap, PF_SYM(AD, U, RW, P));
111 barrier();
112 }
113 else
114 {
115 unsigned long extent = (GB(4) - 1) >> PAGE_SHIFT;
116 struct xen_memory_reservation mr =
117 {
118 .extent_start = &extent,
119 .nr_extents = 1,
120 .domid = DOMID_SELF,
121 };
122
123 /* Populate gfn 0xfffff (the 4GB boundary) with real RAM. */
125 panic("Failed to populate_physmap() at %#lx\n", extent);
126 }
127
128 /*
129 * Copy the instruction stub over the virtual address space wrap.
130 */
131 uint8_t *stub = _p(~0ULL - 5);
132 unsigned int res;
133
134 extern char insn_buf_start[] asm("insn_stub_start");
135 extern char insn_buf_end[] asm("insn_stub_end");
136 memcpy(stub, insn_buf_start, insn_buf_end - insn_buf_start);
137
138 /*
139 * Work around suspected Broadwell TLB Erratum
140 *
141 * Occasionally, this test failes with:
142 *
143 * --- Xen Test Framework ---
144 * Environment: HVM 64bit (Long mode 4 levels)
145 * XSA-186 PoC
146 * ******************************
147 * PANIC: Unhandled exception at 0008:fffffffffffffffa
148 * Vec 14 #PF[-I-sr-] %cr2 fffffffffffffffa
149 * ******************************
150 *
151 * on Broadwell hardware. The mapping is definitely present as the
152 * memcpy() has already succeeded. Inserting an invlpg resolves the
153 * issue, sugguesting that there is a race conditon between dTLB/iTLB
154 * handling.
155 *
156 * Work around the issue for now, to avoid intermittent OSSTest failures
157 * from blocking pushes of unrelated changes.
158 */
159 invlpg(stub);
160
161 /*
162 * Execute the stub.
163 *
164 * Intel CPUs are happy doing this for 32 and 64bit. AMD CPUs are happy
165 * for 64bit, but hit a segment limit violation for 32bit. The Xen
166 * emulator follows AMD behaviour for 32bit guests.
167 *
168 * Cover the segment limit violation with an extable handler, which
169 * matches the `int $N` behaviour. All that matters is that the
170 * instructions don't get lost.
171 */
172 asm volatile ("call *%[ptr];"
173 _ASM_EXTABLE_HANDLER(-1, 0, %P[hnd])
174 : "=a" (res)
175 : "0" (0),
176 [ptr] "r" (stub),
177 [hnd] "p" (ex_fault)
178 : "memory");
179
180 if ( res != 0xc0de )
181 xtf_failure("Fail: Instruction stub wasn't executed correctly\n");
182
183 /*
184 * Execute a 16bit stub.
185 *
186 * Construct a 16bit unreal mode code segment with a 32bit segment limit,
187 * to execute the code with. The stub still runs with 32bit data
188 * segments, which is perfectly valid.
189 */
191 GDTE_SYM(0, 0xfffff, COMMON, CODE, DPL0, R));
192
193 asm volatile ("push $%c[cs16];"
194 "push $1f;"
195 __ASM_SEL(lretl, lretq) ";"
196
197 "1: .code16;"
198 "start_16bit:;"
200 "int $" STR(X86_VEC_AVAIL) ";"
201 "ljmpl $%c[cs], $.Ldone;"
202 "end_16bit:;"
203
204 __ASM_SEL(.code32, .code64) ";"
205 ".Ldone:"
206 : "=a" (res)
207 : "0" (0),
208 [cs] "i" (__KERN_CS),
209 [cs16] "i" (GDTE_AVAIL0 << 3)
210 : "memory");
211
212 if ( res != 0xc0de )
213 xtf_failure("Fail: 16bit code wasn't executed correctly\n");
214
216}
217
218/*
219 * Local variables:
220 * mode: C
221 * c-file-style: "BSD"
222 * c-basic-offset: 4
223 * tab-width: 4
224 * indent-tabs-mode: nil
225 * End:
226 */
#define _ASM_XEN_FEP
Xen Forced Emulation Prefix.
Definition: xen.h:150
#define __ASM_SEL(c, l)
Definition: asm_macros.h:25
static void write_ss(unsigned int ss)
Definition: lib.h:206
static void invlpg(const void *va)
Definition: lib.h:322
static void update_desc(user_desc *ptr, const user_desc new)
Helper to update a live LDT/GDT entry.
Definition: xtf.h:26
#define barrier()
Definition: compiler.h:30
#define __page_aligned_bss
Definition: compiler.h:37
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
user_desc gdt[NR_GDT_ENTRIES]
int xtf_set_idte(unsigned int vector, const struct xtf_idte *idte)
Set up an IDT Entry, in a guest agnostic way.
Definition: traps.c:73
static long hypercall_memory_op(unsigned int cmd, void *arg)
Definition: hypercall.h:100
#define X86_VEC_AVAIL
Available for test use.
Definition: idt.h:20
#define _ASM_EXTABLE_HANDLER(fault, fixup, handler)
Create an exception table entry with custom handler.
Definition: extable.h:38
void panic(const char *fmt,...)
Definition: lib.c:15
#define memcpy(d, s, n)
Definition: libc.h:36
#define STR(x)
Stringise an expression, expanding preprocessor tokens.
Definition: macro_magic.h:17
#define IS_DEFINED(x)
Evalute whether the CONFIG_ token x is defined.
Definition: macro_magic.h:67
#define XENMEM_populate_physmap
Definition: memory.h:10
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
#define GB(num)
Express num in Gigabytes.
Definition: numbers.h:29
#define L2_PT_ENTRIES
Definition: page.h:70
#define L1_PT_ENTRIES
Definition: page.h:69
#define PAGE_SHIFT
Definition: page.h:10
unsigned long intpte_t
Definition: page.h:152
intpte_t pte_from_gfn(unsigned long gfn, uint64_t flags)
intpte_t pte_from_virt(const void *va, uint64_t flags)
#define X86_EXC_GP
Definition: processor.h:115
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define GDTE_DS32_DPL0
Definition: segment.h:29
#define GDTE_AVAIL0
Definition: segment.h:37
#define NULL
Definition: stddef.h:12
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
Exception table entry.
Definition: extable.h:65
Definition: main.c:189
unsigned long * extent_start
Definition: memory.h:13
A guest agnostic represention of IDT information.
Definition: idt.h:27
unsigned long addr
Definition: idt.h:28
#define GDTE_SYM(base, limit,...)
As INIT_GDTE_SYM(), but creates a user_desc object.
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define DOMID_SELF
Definition: xen.h:70
bool test_needs_fep
Boolean indicating whether the test is entirely predicated on the available of the Force Emulation Pr...
Definition: main.c:34
static bool ex_fault(struct cpu_regs *regs, const struct extable_entry *ex)
Definition: main.c:62
static const struct xtf_idte idte
Definition: main.c:47
void test_int_handler(void)
static intpte_t nl2t[L2_PT_ENTRIES]
Definition: main.c:30
static intpte_t nl1t[L1_PT_ENTRIES]
Definition: main.c:31