aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/x86/entry_from_vm86.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index d075ea0e5ca1..f7d9ceac7e06 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -95,6 +95,22 @@ asm (
95 "int3\n\t" 95 "int3\n\t"
96 "vmcode_int80:\n\t" 96 "vmcode_int80:\n\t"
97 "int $0x80\n\t" 97 "int $0x80\n\t"
98 "vmcode_umip:\n\t"
99 /* addressing via displacements */
100 "smsw (2052)\n\t"
101 "sidt (2054)\n\t"
102 "sgdt (2060)\n\t"
103 /* addressing via registers */
104 "mov $2066, %bx\n\t"
105 "smsw (%bx)\n\t"
106 "mov $2068, %bx\n\t"
107 "sidt (%bx)\n\t"
108 "mov $2074, %bx\n\t"
109 "sgdt (%bx)\n\t"
110 /* register operands, only for smsw */
111 "smsw %ax\n\t"
112 "mov %ax, (2080)\n\t"
113 "int3\n\t"
98 ".size vmcode, . - vmcode\n\t" 114 ".size vmcode, . - vmcode\n\t"
99 "end_vmcode:\n\t" 115 "end_vmcode:\n\t"
100 ".code32\n\t" 116 ".code32\n\t"
@@ -103,7 +119,7 @@ asm (
103 119
104extern unsigned char vmcode[], end_vmcode[]; 120extern unsigned char vmcode[], end_vmcode[];
105extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], 121extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[],
106 vmcode_sti[], vmcode_int3[], vmcode_int80[]; 122 vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[];
107 123
108/* Returns false if the test was skipped. */ 124/* Returns false if the test was skipped. */
109static bool do_test(struct vm86plus_struct *v86, unsigned long eip, 125static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
@@ -160,6 +176,58 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
160 return true; 176 return true;
161} 177}
162 178
179void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem)
180{
181 struct table_desc {
182 unsigned short limit;
183 unsigned long base;
184 } __attribute__((packed));
185
186 /* Initialize variables with arbitrary values */
187 struct table_desc gdt1 = { .base = 0x3c3c3c3c, .limit = 0x9999 };
188 struct table_desc gdt2 = { .base = 0x1a1a1a1a, .limit = 0xaeae };
189 struct table_desc idt1 = { .base = 0x7b7b7b7b, .limit = 0xf1f1 };
190 struct table_desc idt2 = { .base = 0x89898989, .limit = 0x1313 };
191 unsigned short msw1 = 0x1414, msw2 = 0x2525, msw3 = 3737;
192
193 /* UMIP -- exit with INT3 unless kernel emulation did not trap #GP */
194 do_test(vm86, vmcode_umip - vmcode, VM86_TRAP, 3, "UMIP tests");
195
196 /* Results from displacement-only addressing */
197 msw1 = *(unsigned short *)(test_mem + 2052);
198 memcpy(&idt1, test_mem + 2054, sizeof(idt1));
199 memcpy(&gdt1, test_mem + 2060, sizeof(gdt1));
200
201 /* Results from register-indirect addressing */
202 msw2 = *(unsigned short *)(test_mem + 2066);
203 memcpy(&idt2, test_mem + 2068, sizeof(idt2));
204 memcpy(&gdt2, test_mem + 2074, sizeof(gdt2));
205
206 /* Results when using register operands */
207 msw3 = *(unsigned short *)(test_mem + 2080);
208
209 printf("[INFO]\tResult from SMSW:[0x%04x]\n", msw1);
210 printf("[INFO]\tResult from SIDT: limit[0x%04x]base[0x%08lx]\n",
211 idt1.limit, idt1.base);
212 printf("[INFO]\tResult from SGDT: limit[0x%04x]base[0x%08lx]\n",
213 gdt1.limit, gdt1.base);
214
215 if (msw1 != msw2 || msw1 != msw3)
216 printf("[FAIL]\tAll the results of SMSW should be the same.\n");
217 else
218 printf("[PASS]\tAll the results from SMSW are identical.\n");
219
220 if (memcmp(&gdt1, &gdt2, sizeof(gdt1)))
221 printf("[FAIL]\tAll the results of SGDT should be the same.\n");
222 else
223 printf("[PASS]\tAll the results from SGDT are identical.\n");
224
225 if (memcmp(&idt1, &idt2, sizeof(idt1)))
226 printf("[FAIL]\tAll the results of SIDT should be the same.\n");
227 else
228 printf("[PASS]\tAll the results from SIDT are identical.\n");
229}
230
163int main(void) 231int main(void)
164{ 232{
165 struct vm86plus_struct v86; 233 struct vm86plus_struct v86;
@@ -218,6 +286,9 @@ int main(void)
218 v86.regs.eax = (unsigned int)-1; 286 v86.regs.eax = (unsigned int)-1;
219 do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80"); 287 do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80");
220 288
289 /* UMIP -- should exit with INTx 0x80 unless UMIP was not disabled */
290 do_umip_tests(&v86, addr);
291
221 /* Execute a null pointer */ 292 /* Execute a null pointer */
222 v86.regs.cs = 0; 293 v86.regs.cs = 0;
223 v86.regs.ss = 0; 294 v86.regs.ss = 0;