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 
39 
40 void entry_NMI_task(void);
41 asm("exit_NMI_task:"
42  "iretl;"
43  "entry_NMI_task:;"
44 
45  "push $0;"
46  "push $" STR(X86_EXC_NMI) ";"
47 
48  "push %es;"
49  "push %ds;"
50 
51  "push %edi;"
52  "push %esi;"
53  "push %edx;"
54  "push %ecx;"
55  "push %eax;"
56  "push %ebx;"
57  "push %ebp;"
58 
59  "push %esp;"
60  "call do_exception;"
61  "add $1*4, %esp;"
62 
63  "pop %ebp;"
64  "pop %ebx;"
65  "pop %eax;"
66  "pop %ecx;"
67  "pop %edx;"
68  "pop %esi;"
69  "pop %edi;"
70 
71  "pop %ds;"
72  "pop %es;"
73 
74  "add $2*4, %esp;" /* entry_vector/error_code. */
75 
76  "jmp exit_NMI_task;");
77 
78 
79 static env_tss nmi_tss __aligned(16) =
80 {
81  .eip = _u(entry_NMI_task),
82  .cs = __KERN_CS,
83  .eflags = X86_EFLAGS_MBS,
84  .esp = _u(nmi_stack + PAGE_SIZE),
85  .ss = __KERN_DS,
86 
87  .ds = __USER_DS,
88  .es = __USER_DS,
89  .fs = __USER_DS,
90  .gs = __USER_DS,
91 
92  .cr3 = _u(cr3_target),
94 };
95 
96 bool do_unhandled_exception(struct cpu_regs *regs)
97 {
98  if ( regs->entry_vector != X86_EXC_NMI )
99  return false;
100 
101  unsigned int curr_ts = str();
102  if ( curr_ts != GDTE_AVAIL0 * 8 )
103  xtf_failure("Fail: Running NMI handler with unexpected %%tr\n"
104  " Expected %04x, got %04x\n", GDTE_AVAIL0 * 8, curr_ts);
105 
106  /* Follow the TSS link pointer to get the interrupted state. */
107  env_tss *t = _p(user_desc_base(&gdt[nmi_tss.link >> 3]));
108 
109  printk(" NMI at %04x:%p, stack %04x:%p\n",
110  t->cs, _p(t->eip), t->ss, _p(t->esp));
111 
112  return true;
113 }
114 
115 static void __user_text user_inject_nmi(void)
116 {
118 }
119 
120 void test_main(void)
121 {
122  unsigned int curr_ts;
123  int rc = apic_init(APIC_MODE_XAPIC);
124 
125  if ( rc )
126  return xtf_error("Error: Unable to set up xapic mode: %d\n", rc);
127 
128  /*
129  * Set up NMI handling to be a task gate.
130  */
132  pack_task_gate(&idt[X86_EXC_NMI], GDTE_AVAIL0 * 8);
133 
134  /*
135  * Send an NMI from supervisor mode, checking that we task switch back to
136  * the expected TSS.
137  */
138  printk("First self-nmi, from supervisor mode\n");
140 
141  if ( (curr_ts = str()) != (GDTE_TSS * 8) )
142  xtf_failure("Fail: Running main task with unexpected %%tr\n"
143  " Expected %04x, got %04x\n", (GDTE_TSS * 8), curr_ts);
144 
145  /*
146  * Send an NMI from user mode, and again check that we are in the expected
147  * task.
148  */
149  printk("Second self-nmi, from user mode\n");
151 
152  if ( (curr_ts = str()) != (GDTE_TSS * 8) )
153  xtf_failure("Fail: Running main task with unexpected %%tr\n"
154  " Expected %04x, got %04x\n", (GDTE_TSS * 8), curr_ts);
155 
156  /*
157  * If Xen is still alive, it handled the user=>supervisor task switch
158  * properly.
159  */
160  xtf_success(NULL);
161 }
162 
163 /*
164  * Local variables:
165  * mode: C
166  * c-file-style: "BSD"
167  * c-basic-offset: 4
168  * tab-width: 4
169  * indent-tabs-mode: nil
170  * End:
171  */
#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:79
#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:38
static void user_inject_nmi(void)
Definition: main.c:115
#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
bool test_wants_user_mappings
Boolean indicating whether the test wants user mappings or not.
Definition: main.c:26
static unsigned int str(void)
Definition: lib.h:352
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
void xtf_error(const char *fmt,...)
Report a test error.
Definition: report.c:80
#define X86_EXC_NMI
Definition: processor.h:93
#define GDTE_TSS
Definition: segment.h:34
static void pack_tss_desc(user_desc *d, const env_tss *t)
Definition: desc.h:203
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:96
__UINT8_TYPE__ uint8_t
Definition: stdint.h:14
#define __aligned(x)
Definition: compiler.h:9