Xen Test Framework
main.c
Go to the documentation of this file.
1 
32 #include <xtf.h>
33 
34 const char test_title[] = "Test nmi-taskswitch-priv";
35 
37 
38 void entry_NMI_task(void);
39 asm("exit_NMI_task:"
40  "iretl;"
41  "entry_NMI_task:;"
42 
43  "push $0;"
44  "push $" STR(X86_EXC_NMI) ";"
45 
46  "push %es;"
47  "push %ds;"
48 
49  "push %edi;"
50  "push %esi;"
51  "push %edx;"
52  "push %ecx;"
53  "push %eax;"
54  "push %ebx;"
55  "push %ebp;"
56 
57  "push %esp;"
58  "call do_exception;"
59  "add $1*4, %esp;"
60 
61  "pop %ebp;"
62  "pop %ebx;"
63  "pop %eax;"
64  "pop %ecx;"
65  "pop %edx;"
66  "pop %esi;"
67  "pop %edi;"
68 
69  "pop %ds;"
70  "pop %es;"
71 
72  "add $2*4, %esp;" /* entry_vector/error_code. */
73 
74  "jmp exit_NMI_task;");
75 
76 
77 static env_tss nmi_tss __aligned(16) =
78 {
79  .eip = _u(entry_NMI_task),
80  .cs = __KERN_CS,
81  .eflags = X86_EFLAGS_MBS,
82  .esp = _u(nmi_stack + PAGE_SIZE),
83  .ss = __KERN_DS,
84 
85  .ds = __USER_DS,
86  .es = __USER_DS,
87  .fs = __USER_DS,
88  .gs = __USER_DS,
89 
90  .cr3 = _u(cr3_target),
92 };
93 
94 bool do_unhandled_exception(struct cpu_regs *regs)
95 {
96  if ( regs->entry_vector != X86_EXC_NMI )
97  return false;
98 
99  unsigned int curr_ts = str();
100  if ( curr_ts != GDTE_AVAIL0 * 8 )
101  xtf_failure("Fail: Running NMI handler with unexpected %%tr\n"
102  " Expected %04x, got %04x\n", GDTE_AVAIL0 * 8, curr_ts);
103 
104  /* Follow the TSS link pointer to get the interrupted state. */
105  env_tss *t = _p(user_desc_base(&gdt[nmi_tss.link >> 3]));
106 
107  printk(" NMI at %04x:%p, stack %04x:%p\n",
108  t->cs, _p(t->eip), t->ss, _p(t->esp));
109 
110  return true;
111 }
112 
113 static void __user_text user_inject_nmi(void)
114 {
116 }
117 
118 void test_main(void)
119 {
120  unsigned int curr_ts;
121  int rc = apic_init(APIC_MODE_XAPIC);
122 
123  if ( rc )
124  return xtf_error("Error: Unable to set up xapic mode: %d\n", rc);
125 
126  /*
127  * Remap the Local APIC MMIO window as USER, so user_inject_nmi() can send
128  * a self-NMI. No INVLPG, as this is a strict relaxing of permissions.
129  */
130  pae_l2_identmap[APIC_DEFAULT_BASE >> PAE_L2_PT_SHIFT] |= _PAGE_USER;
131 
132  /*
133  * Set up NMI handling to be a task gate.
134  */
136  pack_task_gate(&idt[X86_EXC_NMI], GDTE_AVAIL0 * 8);
137 
138  /*
139  * Send an NMI from supervisor mode, checking that we task switch back to
140  * the expected TSS.
141  */
142  printk("First self-nmi, from supervisor mode\n");
144 
145  if ( (curr_ts = str()) != TSS_SEL )
146  xtf_failure("Fail: Running main task with unexpected %%tr\n"
147  " Expected %04x, got %04x\n", TSS_SEL, curr_ts);
148 
149  /*
150  * Send an NMI from user mode, and again check that we are in the expected
151  * task.
152  */
153  printk("Second self-nmi, from user mode\n");
155 
156  if ( (curr_ts = str()) != TSS_SEL )
157  xtf_failure("Fail: Running main task with unexpected %%tr\n"
158  " Expected %04x, got %04x\n", TSS_SEL, curr_ts);
159 
160  /*
161  * If Xen is still alive, it handled the user=>supervisor task switch
162  * properly.
163  */
164  xtf_success(NULL);
165 }
166 
167 /*
168  * Local variables:
169  * mode: C
170  * c-file-style: "BSD"
171  * c-basic-offset: 4
172  * tab-width: 4
173  * indent-tabs-mode: nil
174  * End:
175  */
#define X86_EFLAGS_MBS
Definition: processor.h:8
#define __page_aligned_bss
Definition: compiler.h:37
#define APIC_DEST_SELF
Definition: apic.h:27
static env_tss nmi_tss
Definition: main.c:77
#define APIC_DM_NMI
Definition: apic.h:25
#define _u(v)
Express an arbitrary value v as unsigned long.
Definition: numbers.h:53
int apic_init(enum apic_mode mode)
Discover and initialise the local APIC to the requested mode.
Definition: apic.c:33
void printk(const char *fmt,...)
Definition: console.c:134
#define STR(x)
Stringise an expression, expanding preprocessor tokens.
Definition: macro_magic.h:17
#define __user_text
Definition: compiler.h:33
static unsigned long user_desc_base(const user_desc *d)
Definition: desc.h:179
static void apic_mmio_icr_write(uint64_t val)
Definition: apic.h:59
static uint8_t nmi_stack[PAGE_SIZE]
Definition: main.c:36
static void user_inject_nmi(void)
Definition: main.c:113
#define NULL
Definition: stddef.h:12
void xtf_success(const char *fmt,...)
Report test success.
Definition: report.c:38
#define X86_TSS_INVALID_IO_BITMAP
Definition: x86-tss.h:66
static void exec_user_void(void(*fn)(void))
Definition: lib.h:70
user_desc gdt[NR_GDT_ENTRIES]
void test_main(void)
To be implemented by each test, as its entry point.
Definition: main.c:137
void xtf_failure(const char *fmt,...)
Report a test failure.
Definition: report.c:94
static unsigned int str(void)
Definition: lib.h:366
void entry_NMI_task(void)
const char test_title[]
The title of the test.
Definition: main.c:14
#define GDTE_AVAIL0
Definition: segment.h:37
#define _p(v)
Express an abitrary integer v as void *.
Definition: numbers.h:48
#define PAGE_SIZE
Definition: page.h:11
#define _PAGE_USER
Definition: page.h:27
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
#define APIC_DEFAULT_BASE
Definition: apic.h:31
#define X86_EXC_NMI
Definition: processor.h:104
static void pack_tss_desc(user_desc *d, const env_tss *t)
Definition: desc.h:203
#define PAE_L2_PT_SHIFT
Definition: page-pae.h:33
static void pack_task_gate(env_gate *g, unsigned int selector)
Definition: x86-gate.h:105
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:94
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
#define __aligned(x)
Definition: compiler.h:9