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