Xen Test Framework
main.c
Go to the documentation of this file.
1
33#define TEST_APIC_MODE APIC_MODE_XAPIC
34
35#include <xtf.h>
36
37const char test_title[] = "Test nmi-taskswitch-priv";
38
40
41void entry_NMI_task(void);
42asm("exit_NMI_task:"
43 "iretl;"
44 "entry_NMI_task:;"
45
46 "push $0;"
47 "push $" STR(X86_EXC_NMI) ";"
48
49 "push %es;"
50 "push %ds;"
51
52 "push %edi;"
53 "push %esi;"
54 "push %edx;"
55 "push %ecx;"
56 "push %eax;"
57 "push %ebx;"
58 "push %ebp;"
59
60 "mov %esp, %eax;"
61 "call do_exception;"
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
79static 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
96bool 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
116{
118}
119
120void 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 * Remap the Local APIC MMIO window as USER, so user_inject_nmi() can send
130 * a self-NMI. No INVLPG, as this is a strict relaxing of permissions.
131 */
132 pae_l2_identmap[APIC_DEFAULT_BASE >> PAE_L2_PT_SHIFT] |= _PAGE_USER;
133
134 /*
135 * Set up NMI handling to be a task gate.
136 */
139
140 /*
141 * Send an NMI from supervisor mode, checking that we task switch back to
142 * the expected TSS.
143 */
144 printk("First self-nmi, from supervisor mode\n");
146
147 if ( (curr_ts = str()) != TSS_SEL )
148 xtf_failure("Fail: Running main task with unexpected %%tr\n"
149 " Expected %04x, got %04x\n", TSS_SEL, curr_ts);
150
151 /*
152 * Send an NMI from user mode, and again check that we are in the expected
153 * task.
154 */
155 printk("Second self-nmi, from user mode\n");
157
158 if ( (curr_ts = str()) != TSS_SEL )
159 xtf_failure("Fail: Running main task with unexpected %%tr\n"
160 " Expected %04x, got %04x\n", TSS_SEL, curr_ts);
161
162 /*
163 * If Xen is still alive, it handled the user=>supervisor task switch
164 * properly.
165 */
167}
168
169/*
170 * Local variables:
171 * mode: C
172 * c-file-style: "BSD"
173 * c-basic-offset: 4
174 * tab-width: 4
175 * indent-tabs-mode: nil
176 * End:
177 */
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:45
#define APIC_DM_NMI
Definition: apic.h:30
#define APIC_DEFAULT_BASE
Definition: apic.h:37
static void apic_icr_write(uint64_t val)
Definition: apic.h:121
#define APIC_DEST_SELF
Definition: apic.h:32
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:39
static void user_inject_nmi(void)
Definition: main.c:115
void entry_NMI_task(void)
static env_tss nmi_tss
Definition: main.c:79
bool do_unhandled_exception(struct cpu_regs *regs)
May be implemented by a guest to provide custom exception handling.
Definition: main.c:96
#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