Xen Test Framework
traps.c
Go to the documentation of this file.
1 #include <xtf/traps.h>
2 #include <xtf/lib.h>
3 #include <xtf/hypercall.h>
4 #include <xtf/test.h>
5 
6 #include <arch/idt.h>
7 #include <arch/lib.h>
8 #include <arch/processor.h>
9 #include <arch/segment.h>
10 #include <arch/pagetable.h>
11 #include <arch/symbolic-const.h>
12 
13 /* Filled in by pv/head.S */
15 
16 /* Real entry points */
17 void entry_DE(void);
18 void entry_DB(void);
19 void entry_NMI(void);
20 void entry_BP(void);
21 void entry_OF(void);
22 void entry_BR(void);
23 void entry_UD(void);
24 void entry_NM(void);
25 void entry_DF(void);
26 void entry_TS(void);
27 void entry_NP(void);
28 void entry_SS(void);
29 void entry_GP(void);
30 void entry_PF(void);
31 void entry_MF(void);
32 void entry_AC(void);
33 void entry_MC(void);
34 void entry_XM(void);
35 void entry_VE(void);
36 void entry_ret_to_kernel(void);
37 
38 void entry_SYSCALL(void);
39 void entry_SYSENTER(void);
40 void entry_EVTCHN(void);
41 
43 {
44  { X86_EXC_DE, 0|4, __KERN_CS, _u(entry_DE) },
45  { X86_EXC_DB, 0|4, __KERN_CS, _u(entry_DB) },
46  { X86_EXC_NMI, 0|4, __KERN_CS, _u(entry_NMI) },
47  { X86_EXC_BP, 3|4, __KERN_CS, _u(entry_BP) },
48  { X86_EXC_OF, 3|4, __KERN_CS, _u(entry_OF) },
49  { X86_EXC_BR, 0|4, __KERN_CS, _u(entry_BR) },
50  { X86_EXC_UD, 0|4, __KERN_CS, _u(entry_UD) },
51  { X86_EXC_NM, 0|4, __KERN_CS, _u(entry_NM) },
52  { X86_EXC_DF, 0|4, __KERN_CS, _u(entry_DF) },
53  { X86_EXC_TS, 0|4, __KERN_CS, _u(entry_TS) },
54  { X86_EXC_NP, 0|4, __KERN_CS, _u(entry_NP) },
55  { X86_EXC_SS, 0|4, __KERN_CS, _u(entry_SS) },
56  { X86_EXC_GP, 0|4, __KERN_CS, _u(entry_GP) },
57  { X86_EXC_PF, 0|4, __KERN_CS, _u(entry_PF) },
58  { X86_EXC_MF, 0|4, __KERN_CS, _u(entry_MF) },
59  { X86_EXC_AC, 0|4, __KERN_CS, _u(entry_AC) },
60  { X86_EXC_MC, 0|4, __KERN_CS, _u(entry_MC) },
61  { X86_EXC_XM, 0|4, __KERN_CS, _u(entry_XM) },
62  { X86_EXC_VE, 0|4, __KERN_CS, _u(entry_VE) },
63 
64  { X86_VEC_RET2KERN, 3|4, __KERN_CS, _u(entry_ret_to_kernel) },
65 
66  { 0, 0, 0, 0 }, /* Sentinel. */
67 };
68 
69 int xtf_set_idte(unsigned int vector, const struct xtf_idte *idte)
70 {
71  struct xen_trap_info ti[2] =
72  {
73  { vector, idte->dpl | 4, idte->cs, idte->addr },
74  { 0, 0, 0, 0 }, /* Sentinel. */
75  };
76 
77  return hypercall_set_trap_table(ti);
78 }
79 
80 static int remap_linear(const void *linear, uint64_t flags)
81 {
82  intpte_t nl1e = pte_from_virt(linear, flags);
83 
84  return hypercall_update_va_mapping(_u(linear), nl1e, UVMF_INVLPG);
85 }
86 
87 static int __maybe_unused remap_linear_range(const void *start, const void *end,
89 {
90  int ret = 0;
91 
92  while ( !ret && start < end )
93  {
94  ret = remap_linear(start, flags);
95  start += PAGE_SIZE;
96  }
97 
98  return ret;
99 }
100 
101 static void init_callbacks(void)
102 {
103  /* PV equivalent of `lidt`. */
104  int rc = hypercall_set_trap_table(pv_default_trap_info);
105 
106  if ( rc )
107  panic("Failed to set trap table: %d\n", rc);
108 
109  xen_callback_register_t cb[] = {
110  {
112  .address = INIT_XEN_CALLBACK(__KERN_CS, _u(entry_EVTCHN)),
113  },
114 #ifdef __x86_64__
115  {
116  .type = CALLBACKTYPE_syscall,
117  .flags = CALLBACKF_mask_events,
118  .address = INIT_XEN_CALLBACK(__KERN_CS, _u(entry_SYSCALL)),
119  },
120 #endif
121  {
122  .type = CALLBACKTYPE_syscall32,
123  .flags = CALLBACKF_mask_events,
124  .address = INIT_XEN_CALLBACK(__KERN_CS, _u(entry_SYSCALL)),
125  },
126  {
127  .type = CALLBACKTYPE_sysenter,
128  .flags = CALLBACKF_mask_events,
129  .address = INIT_XEN_CALLBACK(__KERN_CS, _u(entry_SYSENTER)),
130  },
131  };
132 
133  for ( unsigned int i = 0; i < ARRAY_SIZE(cb); ++i )
134  {
135  rc = hypercall_register_callback(&cb[i]);
136  if ( rc )
137  panic("Failed to register callback[%u]: %d\n", i, rc);
138  }
139 }
140 
141 void arch_init_traps(void)
142 {
143  int rc;
144 
145  init_callbacks();
146 
147  /* Register gdt[] with Xen. Need to map it read-only first. */
148  if ( remap_linear(gdt, PF_SYM(AD, P)) )
149  panic("Unable to remap gdt[] as read-only\n");
150 
151  unsigned long gdt_frames[] = {
152  virt_to_mfn(gdt),
153  };
154  BUILD_BUG_ON(NR_GDT_ENTRIES > (PAGE_SIZE / sizeof(user_desc)));
155 
156  rc = hypercall_set_gdt(gdt_frames, NR_GDT_ENTRIES);
157  if ( rc )
158  panic("Failed to set gdt: %d\n", rc);
159 
160  /* PV equivalent of setting tss.{esp0,ss0}. */
161  rc = hypercall_stack_switch(__KERN_DS, &boot_stack[2 * PAGE_SIZE]);
162  if ( rc )
163  panic("Failed to set kernel stack: %d\n", rc);
164 
165  write_ds(__USER_DS);
166  write_es(__USER_DS);
167  write_fs(__USER_DS);
168  write_gs(__USER_DS);
169 
170 #ifdef __x86_64__
171  /*
172  * Set the user pagetables (only applicable to 64bit PV).
173  *
174  * XTF uses a shared user/kernel address space, so register the kernel
175  * %cr3 as the user %cr3.
176  */
177  mmuext_op_t ext =
178  {
180  .arg1.mfn = read_cr3() >> PAGE_SHIFT,
181  };
182 
183  rc = hypercall_mmuext_op(&ext, 1, NULL, DOMID_SELF);
184  if ( rc )
185  panic("Failed to set user %%cr3: %d\n", rc);
186 
187 #elif defined(__i386__)
188  /* Remap the structures which specifically want to be user. */
189  extern const char __start_user_text[], __end_user_text[];
190  extern const char __start_user_data[], __end_user_data[];
191  extern const char __start_user_bss[], __end_user_bss[];
192 
193  remap_linear_range(__start_user_text, __end_user_text,
194  PF_SYM(AD, U, RW, P));
195 
196  remap_linear_range(__start_user_data, __end_user_data,
197  PF_SYM(AD, U, RW, P));
198 
199  remap_linear_range(__start_user_bss, __end_user_bss,
200  PF_SYM(AD, U, RW, P));
201 #endif
202 
203  /* Unmap page at 0 to catch errors with NULL pointers. */
205  if ( rc )
206  panic("Failed to unmap page at NULL: %d\n", rc);
207 }
208 
210 {
211  /*
212  * For both architectures, put the stack pointer into an invalid place and
213  * attempt to use it. Xen should fail to create a bounce frame and crash
214  * the domain.
215  */
216  asm volatile(
217  "mov %0, %%" _ASM_SP ";"
218  "pushf"
219  ::
220 #ifdef __i386__
221  "i" (0xfbadc0deUL) /* 32bit: In the read-only M2P mapping. */
222 #else
223  "i" (0x800000000badc0deUL) /* 64bit: Non-canonical region. */
224 #endif
225  : "memory" );
226 
227  /*
228  * Attempt to crash failed. Give up and sit in a loop.
229  */
230  asm volatile("1: hlt;"
231  "pause;"
232  "jmp 1b"
233  ::: "memory");
234  unreachable();
235 }
236 
237 /*
238  * Local variables:
239  * mode: C
240  * c-file-style: "BSD"
241  * c-basic-offset: 4
242  * tab-width: 4
243  * indent-tabs-mode: nil
244  * End:
245  */
void entry_NP(void)
static void init_callbacks(void)
Definition: traps.c:101
static long hypercall_set_trap_table(const struct xen_trap_info *ti)
Definition: hypercall.h:55
void entry_OF(void)
API for tests.
uint8_t flags
Definition: xen.h:34
void entry_BR(void)
#define MMUEXT_NEW_USER_BASEPTR
Definition: xen.h:347
Macros for creating constants using mnemonics.
void arch_crash_hard(void)
Definition: traps.c:142
#define __noreturn
Definition: compiler.h:10
static long hypercall_update_va_mapping(unsigned long linear, uint64_t npte, enum XEN_UVMF flags)
Definition: hypercall.h:115
void entry_AC(void)
static int remap_linear(const void *linear, uint64_t flags)
Definition: traps.c:80
unsigned long addr
Definition: idt.h:28
void entry_PF(void)
#define ARRAY_SIZE(a)
Definition: lib.h:8
#define X86_EXC_DF
Definition: processor.h:110
#define X86_EXC_MF
Definition: processor.h:118
void entry_ret_to_kernel(void)
#define X86_EXC_OF
Definition: processor.h:106
static int hypercall_register_callback(const xen_callback_register_t *arg)
Definition: hypercall.h:218
#define CALLBACKTYPE_event
Definition: callback.h:18
void entry_GP(void)
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
x86 IDT vector infrastructure.
#define X86_EXC_MC
Definition: processor.h:120
intpte_t pte_from_virt(const void *va, uint64_t flags)
#define X86_EXC_GP
Definition: processor.h:115
void panic(const char *fmt,...)
Definition: lib.c:15
#define X86_EXC_NM
Definition: processor.h:109
void entry_UD(void)
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
static long hypercall_stack_switch(const unsigned int ss, const void *sp)
Definition: hypercall.h:75
void entry_SYSCALL(void)
void entry_DB(void)
static void write_gs(unsigned int gs)
Definition: lib.h:201
#define PF_SYM(...)
Create pagetable entry flags based on mnemonics.
#define X86_EXC_BP
Definition: processor.h:105
#define X86_EXC_DE
Definition: processor.h:102
void entry_MF(void)
uint8_t vector
Definition: xen.h:33
unsigned int cs
Definition: idt.h:29
#define X86_EXC_XM
Definition: processor.h:121
unsigned long virt_to_mfn(const void *va)
void entry_TS(void)
#define NULL
Definition: stddef.h:12
void entry_MC(void)
void entry_NMI(void)
#define CALLBACKTYPE_syscall32
Definition: callback.h:49
void entry_DE(void)
void arch_init_traps(void)
Definition: traps.c:86
void entry_VE(void)
static int remap_linear_range(const void *start, const void *end, uint64_t flags)
Definition: traps.c:87
static unsigned long read_cr3(void)
Definition: lib.h:243
user_desc gdt[NR_GDT_ENTRIES]
__UINT64_TYPE__ uint64_t
Definition: stdint.h:17
#define CALLBACKF_mask_events
Definition: callback.h:56
Definition: xen.h:355
#define CALLBACKTYPE_syscall
Definition: callback.h:24
static void write_ds(unsigned int ds)
Definition: lib.h:186
void entry_BP(void)
#define X86_EXC_NP
Definition: processor.h:113
static void write_es(unsigned int es)
Definition: lib.h:191
unsigned long intpte_t
Definition: page.h:152
static const struct xtf_idte idte
Definition: main.c:164
#define CALLBACKTYPE_sysenter
Definition: callback.h:43
static long hypercall_set_gdt(const unsigned long *mfns, unsigned int entries)
Definition: hypercall.h:69
unsigned int dpl
Definition: idt.h:29
#define PAGE_SHIFT
Definition: page.h:10
#define X86_EXC_UD
Definition: processor.h:108
#define X86_EXC_VE
Definition: processor.h:122
void entry_XM(void)
#define X86_EXC_AC
Definition: processor.h:119
#define INIT_XEN_CALLBACK(_cs, _ip)
Definition: xen-x86_32.h:88
#define unreachable()
Definition: compiler.h:29
uint8_t boot_stack[3 *PAGE_SIZE]
Definition: setup.c:21
#define X86_EXC_DB
Definition: processor.h:103
#define X86_EXC_BR
Definition: processor.h:107
#define PAGE_SIZE
Definition: page.h:11
#define X86_VEC_RET2KERN
Return to kernel mode.
Definition: idt.h:15
A guest agnostic represention of IDT information.
Definition: idt.h:26
#define _ASM_SP
Definition: asm_macros.h:37
static long hypercall_mmuext_op(const mmuext_op_t ops[], unsigned int count, unsigned int *done, unsigned int foreigndom)
Definition: hypercall.h:148
#define X86_EXC_NMI
Definition: processor.h:104
#define X86_EXC_SS
Definition: processor.h:114
void entry_NM(void)
struct xen_trap_info pv_default_trap_info[]
Definition: traps.c:42
#define X86_EXC_TS
Definition: processor.h:112
#define BUILD_BUG_ON(cond)
Definition: lib.h:24
unsigned int cmd
Definition: xen.h:356
xen_pv_start_info_t * pv_start_info
Definition: traps.c:14
#define DOMID_SELF
Definition: xen.h:70
#define X86_EXC_PF
Definition: processor.h:116
#define __maybe_unused
Definition: compiler.h:13
static void write_fs(unsigned int fs)
Definition: lib.h:196
#define NR_GDT_ENTRIES
Definition: segment.h:44
void entry_SYSENTER(void)
void entry_DF(void)
void entry_SS(void)
void entry_EVTCHN(void)