VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bootsector2-cpu-xcpt-1-template.mac@ 66257

Last change on this file since 66257 was 62484, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.2 KB
Line 
1; $Id: bootsector2-cpu-xcpt-1-template.mac 62484 2016-07-22 18:35:33Z vboxsync $
2;; @file
3; Bootsector test for basic exceptions - multi mode template.
4;
5
6;
7; Copyright (C) 2007-2016 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; The contents of this file may alternatively be used under the terms
18; of the Common Development and Distribution License Version 1.0
19; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20; VirtualBox OSE distribution, in which case the provisions of the
21; CDDL are applicable instead of those of the GPL.
22;
23; You may elect to license modified versions of this file under the
24; terms and conditions of either the GPL or the CDDL or both.
25;
26
27
28%include "bootsector2-template-header.mac"
29
30
31;*******************************************************************************
32;* Defined Constants And Macros *
33;*******************************************************************************
34;;
35; Some 32/64 macros.
36;
37%if TMPL_BITS == 32
38 %define bs2Idt_BP bs2Idt32bit_BP
39 %define MY_R0_CS BS2_SEL_CS32
40 %define MY_R1_CS BS2_SEL_R1_CS32
41 %define MY_R2_CS BS2_SEL_R2_CS32
42 %define MY_R3_CS BS2_SEL_R3_CS32
43
44 %define MY_R0_DS BS2_SEL_DS32
45 %define MY_R1_DS BS2_SEL_R1_DS32
46 %define MY_R2_DS BS2_SEL_R2_DS32
47 %define MY_R3_DS BS2_SEL_R3_DS32
48
49 %define MY_R0_SS BS2_SEL_SS32
50 %define MY_R1_SS BS2_SEL_R1_SS32
51 %define MY_R2_SS BS2_SEL_R2_SS32
52 %define MY_R3_SS BS2_SEL_R3_SS32
53
54%else
55 %define bs2Idt_BP bs2Idt64bit_BP
56 %define MY_R0_CS BS2_SEL_CS64
57 %define MY_R1_CS BS2_SEL_R1_CS64
58 %define MY_R2_CS BS2_SEL_R2_CS64
59 %define MY_R3_CS BS2_SEL_R3_CS64
60
61 %define MY_R0_DS BS2_SEL_DS64
62 %define MY_R1_DS BS2_SEL_R1_DS64
63 %define MY_R2_DS BS2_SEL_R2_DS64
64 %define MY_R3_DS BS2_SEL_R3_DS64
65
66 %define MY_R0_SS BS2_SEL_SS64
67 %define MY_R1_SS BS2_SEL_R1_SS64
68 %define MY_R2_SS BS2_SEL_R2_SS64
69 %define MY_R3_SS BS2_SEL_R3_SS64
70%endif
71
72%ifdef TMPL_64BIT
73 %assign MY_IS_64BIT 1
74%else
75 %assign MY_IS_64BIT 0
76%endif
77
78
79;*******************************************************************************
80;* Global Variables *
81;*******************************************************************************
82%ifndef CPU_XCPT_1_GLOBALS
83 %define CPU_XCPT_1_GLOBALS
84 g_szWrongIfStateFmt:
85 db 'Wrong IF state (0x%RX32) on line 0x%RX32', 0
86 g_szWrongHandlerCsFmt:
87 db 'Wrong handler CS=%RX16, expected %RX16 (line 0x%RX32)', 0
88 g_szWrongCurCsFmt:
89 db 'Wrong CS=%RX16, expected %RX16 (line 0x%RX32)', 0
90 g_szWrongCurSRegFmt_fs:
91 db 'Wrong FS=%RX16, expected %RX16 (line 0x%RX32)', 0
92 g_szWrongCurSRegFmt_ss:
93 db 'Wrong SS=%RX16, expected %RX16 (line 0x%RX32)', 0
94
95
96;;
97; Asserts a test.
98;
99; @param %1 First cmp operand.
100; @param %2 First cmp operand.
101; @param %3 Which kind of conditional jump to make
102; @param %4 The message to print (format string, no arguments please).
103;
104%macro ASSERT_SIMPLE 4
105 cmp %1, %2
106 %3 %%.ok
107 push dword __LINE__
108 %ifdef TMPL_16BIT
109 push ds
110 %endif
111 push %%.s_szMsg
112 call TMPL_NM_CMN(TestFailedF)
113 add xSP, sCB*2
114 jmp %%.ok
115%%.s_szMsg: db %4, " (0x%RX32)", 0
116%%.ok:
117%endmacro
118
119
120 ;;
121 ; Asserts that the IF flag is set or clear when the trap handler was called.
122 ;
123 ; @param 1 jnz or jz.
124 ;
125 ; @uses rax, flags, and stack.
126 ;
127 %macro ASSERT_TRAP_EFLAGS_IF 1
128 test word [g_u64LastTrapHandlerRFlags xWrtRIP], X86_EFL_IF
129 %1 %%.ok
130 %ifdef TMPL_LM64
131 push __LINE__
132 push qword [g_u64LastTrapHandlerRFlags xWrtRIP]
133 lea rax, [g_szWrongIfStateFmt wrt RIP]
134 push rax
135 call TMPL_NM_CMN(TestFailedF)
136 add xSP, 24
137 %elifdef TMPL_16
138 push dword __LINE__
139 push dword [g_u64LastTrapHandlerRFlags]
140 push cs
141 push g_szWrongIfStateFmt
142 call TMPL_NM_CMN(TestFailedF)
143 add xSP, 12
144 %else
145 push __LINE__
146 push dword [g_u64LastTrapHandlerRFlags]
147 push g_szWrongIfStateFmt
148 call TMPL_NM_CMN(TestFailedF)
149 add xSP, 12
150 %endif
151 %%.ok:
152 %endmacro
153
154
155 ;;
156 ; Asserts that a certain CS value when the trap handler was called.
157 ;
158 ; @param 1 The CS value.
159 ;
160 ; @uses rax, flags, and stack.
161 ;
162 %macro ASSERT_TRAP_CS_VALUE 1
163 cmp word [g_u16LastTrapHandlerCS xWrtRIP], (%1)
164 je %%.ok
165 %ifdef TMPL_LM64
166 push __LINE__
167 push (%1)
168 movzx eax, word [g_u16LastTrapHandlerCS xWrtRIP]
169 push rax
170 lea rax, [g_szWrongHandlerCsFmt wrt RIP]
171 push rax
172 call TMPL_NM_CMN(TestFailedF)
173 add xSP, 32
174 %elifdef TMPL_16
175 push dword __LINE__
176 push word (%1)
177 push word [g_u16LastTrapHandlerCS]
178 push cs
179 push g_szWrongHandlerCsFmt
180 call TMPL_NM_CMN(TestFailedF)
181 add xSP, 12
182 %else
183 push __LINE__
184 push (%1)
185 movzx eax, word [g_u16LastTrapHandlerCS]
186 push eax
187 push g_szWrongHandlerCsFmt
188 call TMPL_NM_CMN(TestFailedF)
189 add xSP, 16
190 %endif
191 %%.ok:
192 %endmacro
193
194 ;;
195 ; Asserts that a certain CS value right now, CS being loaded in BX.
196 ;
197 ; @param bx The CS value.
198 ; @param 1 The expected CS value.
199 ;
200 ; @uses rax, flags, and stack.
201 ;
202 %macro ASSERT_CUR_CS_VALUE_IN_BX 1
203 cmp bx, (%1)
204 je %%.ok
205 %ifdef TMPL_LM64
206 push __LINE__
207 push (%1)
208 push rbx
209 lea rax, [g_szWrongCurCsFmt wrt RIP]
210 push rax
211 call TMPL_NM_CMN(TestFailedF)
212 add xSP, 32
213 %elifdef TMPL_16
214 push dword __LINE__
215 push word (%1)
216 push bx
217 push g_szWrongCurCsFmt
218 call TMPL_NM_CMN(TestFailedF)
219 add xSP, 12
220 %else
221 push __LINE__
222 push (%1)
223 push ebx
224 push g_szWrongCurCsFmt
225 call TMPL_NM_CMN(TestFailedF)
226 add xSP, 16
227 %endif
228 %%.ok:
229 %endmacro
230
231 ;;
232 ; Asserts that the given segment register has a certain value right now.
233 ;
234 ; @param 1 The segment register
235 ; @param 2 The value.
236 ;
237 ; @uses rax, flags, and stack.
238 ;
239 %macro ASSERT_CUR_SREG_VALUE 2
240 mov ax, %1
241 cmp ax, (%2)
242 je %%.ok
243 %ifdef TMPL_LM64
244 push __LINE__
245 push (%2)
246 push rax
247 lea rax, [g_szWrongCurSRegFmt_ %+ %1 wrt RIP]
248 push rax
249 call TMPL_NM_CMN(TestFailedF)
250 add xSP, 32
251 %elifdef TMPL_16
252 push dword __LINE__
253 push word (%2)
254 push ax
255 push g_szWrongCurSRegFmt_ %+ %1
256 call TMPL_NM_CMN(TestFailedF)
257 add xSP, 12
258 %else
259 push __LINE__
260 push (%2)
261 push eax
262 push g_szWrongCurSRegFmt_ %+ %1
263 call TMPL_NM_CMN(TestFailedF)
264 add xSP, 16
265 %endif
266 %%.ok:
267 %endmacro
268
269
270%endif
271
272
273;;
274; Checks different gate types.
275;
276BEGINPROC TMPL_NM(TestGateType)
277 push xBP
278 mov xBP, xSP
279 push sAX
280 push xBX
281 push xCX
282 push xDX
283 push xDI
284 push xSI
285
286 mov xAX, .s_szSubTestName
287 call TMPL_NM_CMN(TestSub)
288
289
290 ;
291 ; Check that int3 works and save the IDTE before making changes.
292 ;
293 ; We'll be changing X86DESCGATE.u4Type, which starts at bit 0x28 (that
294 ; is byte 5) and is 4-bit wide, and X86DESCGATE.u1DescType, which is
295 ; at bit 2c.
296 ;
297 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check that int3 works before we start messing around...
298
299%ifdef TMPL_LM64
300 push qword [bs2Idt_BP xWrtRIP]
301 push qword [bs2Idt_BP + 8 xWrtRIP]
302%else
303 push dword [bs2Idt_BP xWrtRIP]
304 push dword [bs2Idt_BP + 4 xWrtRIP]
305%endif
306 mov xDI, xSP ; for catching stack errors
307
308 ;
309 ; Check all kinds of none system selectors first (they should all GP(3+IDT))
310 ;
311%assign u4Type 0
312%rep 16
313 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
314 or byte [bs2Idt_BP + 5 xWrtRIP], RT_BIT(4) | u4Type
315 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
316 %assign u4Type (u4Type + 1)
317%endrep
318
319 ;
320 ; Illegal system types.
321 ;
322%ifdef TMPL_LM64
323 %assign u4Type 0
324 %rep 14
325 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
326 or byte [bs2Idt_BP + 5 xWrtRIP], u4Type
327 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
328 %assign u4Type (u4Type + 1)
329 %endrep
330%else
331 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
332 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_UNDEFINED
333 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
334
335 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
336 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_286_TSS_AVAIL
337 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
338
339 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
340 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_LDT
341 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
342
343 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
344 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_286_TSS_BUSY
345 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
346
347 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
348 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_286_CALL_GATE
349 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
350
351 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
352 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_UNDEFINED2
353 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
354
355 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
356 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_TSS_AVAIL
357 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
358
359 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
360 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_UNDEFINED3
361 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
362
363 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
364 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_TSS_BUSY
365 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
366
367 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
368 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_UNDEFINED4
369 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
370
371 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
372 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_CALL_GATE
373 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
374%endif
375
376 ;
377 ; Legal types.
378 ;
379 pushf
380 sti ; make sure interrupts are enabled.
381
382%ifdef TMPL_LM64
383 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
384 or byte [bs2Idt_BP + 5 xWrtRIP], AMD64_SEL_TYPE_SYS_INT_GATE
385 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
386 ASSERT_TRAP_EFLAGS_IF jz
387
388 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
389 or byte [bs2Idt_BP + 5 xWrtRIP], AMD64_SEL_TYPE_SYS_TRAP_GATE
390 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
391 ASSERT_TRAP_EFLAGS_IF jnz
392%else
393 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
394 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_INT_GATE
395 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
396 ASSERT_TRAP_EFLAGS_IF jz
397
398 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
399 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_TRAP_GATE
400 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
401 ASSERT_TRAP_EFLAGS_IF jnz
402
403 ;; @todo X86_SEL_TYPE_SYS_TASK_GATE, X86_SEL_TYPE_SYS_286_INT_GATE, X86_SEL_TYPE_SYS_286_TRAP_GATE, X86_SEL_TYPE_SYS_386_CALL_GATE
404%endif
405
406 popf
407
408 ;
409 ; Check that a not-present gate GPs. The not-present bit is 0x2f.
410 ;
411 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
412%ifdef TMPL_LM64
413 or byte [bs2Idt_BP + 5 xWrtRIP], AMD64_SEL_TYPE_SYS_INT_GATE
414%else
415 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_TRAP_GATE
416%endif
417 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
418
419 and byte [bs2Idt_BP + 5 xWrtRIP], 07fh
420 BS2_TRAP_INSTR X86_XCPT_NP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
421
422 ;
423 ; Restore the descriptor and make sure it works.
424 ;
425 ASSERT_SIMPLE xDI, xSP, je, "Someone busted xSP during this test."
426%ifdef TMPL_LM64
427 pop qword [bs2Idt_BP + 8 xWrtRIP]
428 pop qword [bs2Idt_BP xWrtRIP]
429%else
430 pop dword [bs2Idt_BP + 4 xWrtRIP]
431 pop dword [bs2Idt_BP xWrtRIP]
432%endif
433 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
434
435 ;
436 ; Done.
437 ;
438 call TMPL_NM_CMN(TestSubDone)
439
440 pop xSI
441 pop xDI
442 pop xDX
443 pop xCX
444 pop xBX
445 pop sAX
446 leave
447 ret
448
449.s_szSubTestName:
450 db TMPL_MODE_STR, ', IDTE type checks', 0
451ENDPROC TMPL_NM(TestGateType)
452
453
454;;
455; Checks different code selector types.
456;
457; @uses No registers, but BS2_SEL_SPARE0 is trashed.
458;
459BEGINPROC TMPL_NM(TestCodeSelector)
460 push xBP
461 mov xBP, xSP
462 push sAX
463 push xBX
464 push xCX
465 push xDX
466 push xDI
467 push xSI
468
469 mov xAX, .s_szSubTestName
470 call TMPL_NM_CMN(TestSub)
471
472
473 ;
474 ; Modify the first extra selector to be various kinds of invalid code
475 ; selectors.
476 ;
477 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check that int3 works before we start messing around...
478
479%ifdef TMPL_LM64
480 push qword [bs2Idt_BP xWrtRIP]
481 push qword [bs2Idt_BP + 8 xWrtRIP]
482%else
483 push dword [bs2Idt_BP xWrtRIP]
484 push dword [bs2Idt_BP + 4 xWrtRIP]
485%endif
486
487 mov ecx, [bs2Gdt + MY_R0_CS xWrtRIP]
488 mov [bs2GdtSpare0 xWrtRIP], ecx
489 mov ecx, [bs2Gdt + MY_R0_CS + 4 xWrtRIP]
490 mov [bs2GdtSpare0 + 4 xWrtRIP], ecx ; GdtSpare0 is a copy of the CS descriptor now.
491
492 mov word [bs2Idt_BP + 2 xWrtRIP], BS2_SEL_SPARE0
493
494 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check again to make sure the CS copy is fine.
495
496
497 ; Data selector (u4Type starts at bit 0x28, that is byte 5) .
498 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
499 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RO
500 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
501
502 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
503 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RO_ACC
504 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
505
506 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
507 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RW
508 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
509
510 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
511 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RW_ACC
512 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
513
514 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
515 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RO_DOWN
516 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
517
518 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
519 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RO_DOWN_ACC
520 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
521
522 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
523 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RW_DOWN
524 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
525
526 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
527 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RW_DOWN_ACC
528 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
529
530 ; Executable selector types (works fine).
531 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
532 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_EO
533 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
534
535 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
536 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_EO_ACC
537 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
538
539 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
540 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER
541 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
542
543 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
544 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_ACC
545 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
546
547 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
548 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_EO_CONF
549 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
550
551 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
552 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_EO_CONF_ACC
553 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
554
555 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
556 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_CONF
557 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
558
559 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
560 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_CONF_ACC
561 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
562
563 ;
564 ; Test with the code selector set to NULL.
565 ;
566 mov word [bs2Idt_BP + 2 xWrtRIP], 0
567 BS2_TRAP_INSTR X86_XCPT_GP, 0, int3
568
569 mov word [bs2Idt_BP + 2 xWrtRIP], 1
570 BS2_TRAP_INSTR X86_XCPT_GP, 0, int3
571
572 mov word [bs2Idt_BP + 2 xWrtRIP], 2
573 BS2_TRAP_INSTR X86_XCPT_GP, 0, int3
574
575 mov word [bs2Idt_BP + 2 xWrtRIP], 3
576 BS2_TRAP_INSTR X86_XCPT_GP, 0, int3
577
578 mov word [bs2Idt_BP + 2 xWrtRIP], BS2_SEL_SPARE0 ; restore our CS
579
580 ;
581 ; Test with the code selector marked as not present but otherwise valid.
582 ;
583 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
584 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_ACC
585 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
586
587 and byte [bs2GdtSpare0 + 5 xWrtRIP], 07fh
588 BS2_TRAP_INSTR X86_XCPT_NP, BS2_SEL_SPARE0, int3
589
590 ;
591 ; Invalid CS selector and not present, we should get a GP.
592 ; Intel states that the present bit is checked after the type.
593 ;
594 and byte [bs2GdtSpare0 + 5 xWrtRIP], 070h
595 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RW_DOWN_ACC
596 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
597
598%ifdef TMPL_LM64
599 ; Long mode variations on invalid (L and D bits) pitted against NP.
600 and byte [bs2GdtSpare0 + 5 xWrtRIP], 070h
601 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_ACC
602 and byte [bs2GdtSpare0 + 6 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6)) ; (0x35=u1Long, 0x36=u1DefBig) = (0, 0)
603 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
604
605 or byte [bs2GdtSpare0 + 6 xWrtRIP], RT_BIT(6) ; (0x35=u1Long, 0x36=u1DefBig) = (0, 1)
606 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
607
608 or byte [bs2GdtSpare0 + 6 xWrtRIP], RT_BIT(5) ; (0x35=u1Long, 0x36=u1DefBig) = (1, 1)
609 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
610
611 and byte [bs2GdtSpare0 + 6 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6))
612 or byte [bs2GdtSpare0 + 6 xWrtRIP], RT_BIT(5) ; restored
613%endif
614
615 and byte [bs2GdtSpare0 + 5 xWrtRIP], 070h
616 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_ACC | 080h ; restore CS to present & valid.
617 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; make sure this is so.
618
619 ;
620 ; Check the CS DPL vs IDTE DPL.
621 ; X86DESCGENERIC.u2Dpl is at bit 0x2d (i.e. in byte 5).
622 ;
623 and byte [bs2GdtSpare0 + 5 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6))
624 or byte [bs2GdtSpare0 + 5 xWrtRIP], 0 ; CS.DPL == 0 == CPL
625 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
626
627 and byte [bs2GdtSpare0 + 5 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6))
628 or byte [bs2GdtSpare0 + 5 xWrtRIP], 1 << 5 ; CS.DPL == 1 < CPL
629 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
630
631 and byte [bs2GdtSpare0 + 5 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6))
632 or byte [bs2GdtSpare0 + 5 xWrtRIP], 2 << 5 ; CS.DPL == 2 < CPL
633 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
634
635 and byte [bs2GdtSpare0 + 5 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6))
636 or byte [bs2GdtSpare0 + 5 xWrtRIP], 3 << 5 ; CS.DPL == 3 < CPL
637 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
638
639 ; Restore.
640 and byte [bs2GdtSpare0 + 5 xWrtRIP], 010h
641 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_ACC | 080h ; restore CS to present, valid and DPL=0
642 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; make sure it's restored.
643
644 ;
645 ; Is RPL is ignored? Yes, it is.
646 ;
647 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL ; RPL = 0
648 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
649 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0
650
651 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL
652 or byte [bs2Idt_BP + 2 xWrtRIP], 1 ; RPL = 1
653 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
654 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0
655
656 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL
657 or byte [bs2Idt_BP + 2 xWrtRIP], 2 ; RPL = 2
658 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
659 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0
660
661 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL
662 or byte [bs2Idt_BP + 2 xWrtRIP], 3 ; RPL = 3
663 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
664 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0
665
666 ;
667 ; Conforming CS.
668 ;
669 or byte [bs2Idt_BP + 5 xWrtRIP], (3 << 5) ; IDTE.DPL = 3
670 and byte [bs2GdtSpare0 + 5 xWrtRIP], 090h
671 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_CONF_ACC ; CS.DPL=0, code, read, conforming
672
673 call TMPL_NM_CMN(Bs2ToRing1)
674 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
675 call TMPL_NM_CMN(Bs2ToRing0)
676 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 1
677
678 call TMPL_NM_CMN(Bs2ToRing2)
679 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
680 call TMPL_NM_CMN(Bs2ToRing0)
681 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 2
682
683 call TMPL_NM_CMN(Bs2ToRing3)
684 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
685 call TMPL_NM_CMN(Bs2ToRing0)
686 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 3
687
688 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
689 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 0
690
691 ; RPL is ignored. Only CPL matters.
692 or byte [bs2Idt_BP + 2 xWrtRIP], (3 << 5) ; IDTE.CS.RPL=3
693 call TMPL_NM_CMN(Bs2ToRing2)
694 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
695 call TMPL_NM_CMN(Bs2ToRing0)
696 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 2
697
698 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL
699 or byte [bs2Idt_BP + 2 xWrtRIP], (1 << 5) ; IDTE.CS.RPL=1
700 call TMPL_NM_CMN(Bs2ToRing2)
701 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
702 call TMPL_NM_CMN(Bs2ToRing0)
703 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 2
704
705 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL
706 or byte [bs2Idt_BP + 2 xWrtRIP], (2 << 5) ; IDTE.CS.RPL=2
707 call TMPL_NM_CMN(Bs2ToRing2)
708 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
709 call TMPL_NM_CMN(Bs2ToRing0)
710 ASSERT_TRAP_CS_VALUE BS2_SEL_SPARE0 | 2
711
712 ; Change the CS.DPL to 1 and try it from ring-0.
713 and byte [bs2GdtSpare0 + 5 xWrtRIP], 09fh
714 or byte [bs2GdtSpare0 + 5 xWrtRIP], (1 << 5) ; CS.DPL=1
715 BS2_TRAP_INSTR X86_XCPT_GP, BS2_SEL_SPARE0, int3
716
717 ; Restore.
718 and word [bs2Idt_BP + 2 xWrtRIP], X86_SEL_MASK_OFF_RPL
719 and byte [bs2Idt_BP + 5 xWrtRIP], 0x9f ; IDTE.DPL=0
720 and byte [bs2GdtSpare0 + 5 xWrtRIP], 010h
721 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_ER_ACC | 080h ; restore CS to present, valid and DPL=0
722 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; make sure it's restored.
723
724 ;
725 ; Limit / canonical checks.
726 ;
727 ; Messing with X86DESCGENERIC.u16LimitLow which is at bit 0,
728 ; X86DESCGENERIC.u4LimitHigh which is at bit 0x30, and
729 ; X86DESCGENERIC.u1Granularity which is at bit 0x37.
730 ;
731 mov word [bs2GdtSpare0 xWrtRIP], 0010h
732 and byte [bs2GdtSpare0 + 6 xWrtRIP], 070h ; setting limit to 0x10, ASSUMES IDTE.off > 0x10
733%ifdef TMPL_LM64
734 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
735%else
736 BS2_TRAP_INSTR X86_XCPT_GP, 0, int3
737%endif
738
739%ifdef TMPL_LM64
740 or dword [bs2Idt_BP + 8 xWrtRIP], 0x007f7f33
741 BS2_TRAP_INSTR X86_XCPT_GP, 0, int3
742%endif
743
744 ; Who takes precedence? CS NP or the above GP? NP does.
745 and byte [bs2GdtSpare0 + 5 xWrtRIP], 07fh
746 BS2_TRAP_INSTR X86_XCPT_NP, BS2_SEL_SPARE0, int3
747
748
749%ifdef TMPL_LM64
750 ; Who takes precedence? IDTE NP or the not canoncial GP? NP does.
751 or byte [bs2GdtSpare0 + 5 xWrtRIP], 80h
752 and byte [bs2Idt_BP + 5 xWrtRIP], 07fh
753 BS2_TRAP_INSTR X86_XCPT_NP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
754%endif
755
756 ;
757 ; Restore the descriptor and make sure it works.
758 ;
759%ifdef TMPL_LM64
760 pop qword [bs2Idt_BP + 8 xWrtRIP]
761 pop qword [bs2Idt_BP xWrtRIP]
762%else
763 pop dword [bs2Idt_BP + 4 xWrtRIP]
764 pop dword [bs2Idt_BP xWrtRIP]
765%endif
766 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
767
768 ;
769 ; Done.
770 ;
771 call TMPL_NM_CMN(TestSubDone)
772
773 pop xSI
774 pop xDI
775 pop xDX
776 pop xCX
777 pop xBX
778 pop sAX
779 leave
780 ret
781
782.s_szSubTestName:
783 db TMPL_MODE_STR, ', IDTE CS checks', 0
784ENDPROC TMPL_NM(TestCodeSelector)
785
786
787;;
788; Checks that the IDTE type is checked before the CS type.
789;
790; @uses No registers, but BS2_SEL_SPARE0 is trashed.
791;
792BEGINPROC TMPL_NM(TestCheckOrderCsTypeVsIdteType)
793 push xBP
794 mov xBP, xSP
795 push sAX
796 push xBX
797 push xCX
798 push xDX
799 push xDI
800 push xSI
801
802 mov xAX, .s_szSubTestName
803 call TMPL_NM_CMN(TestSub)
804
805
806 ;
807 ; Check the int3 and save its IDTE.
808 ;
809 ; We'll be changing X86DESCGATE.u4Type, which starts at bit 0x28 (that
810 ; is byte 5) and is 4-bit wide, and X86DESCGATE.u1DescType, which is
811 ; at bit 2c.
812 ;
813 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check that int3 works before we start messing around...
814
815%ifdef TMPL_LM64
816 push qword [bs2Idt_BP xWrtRIP]
817 push qword [bs2Idt_BP + 8 xWrtRIP]
818%else
819 push dword [bs2Idt_BP xWrtRIP]
820 push dword [bs2Idt_BP + 4 xWrtRIP]
821%endif
822
823 ;
824 ; Make a copy of our CS descriptor into spare one and make INT3 use it.
825 ;
826 mov ecx, [bs2Gdt + MY_R0_CS xWrtRIP]
827 mov [bs2GdtSpare0 xWrtRIP], ecx
828 mov ecx, [bs2Gdt + MY_R0_CS + 4 xWrtRIP]
829 mov [bs2GdtSpare0 + 4 xWrtRIP], ecx ; GdtSpare0 is a copy of the CS descriptor now.
830
831 mov word [bs2Idt_BP + 2 xWrtRIP], BS2_SEL_SPARE0
832
833 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check again to make sure the CS copy is fine.
834
835 ;
836 ; Make both the IDTE type and CS invalid, we should end up with a IDT GP not the CS one.
837 ; CS = data selector and IDTE invalid 0 type.
838 ;
839 and byte [bs2GdtSpare0 + 5 xWrtRIP], 0f0h
840 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_RO
841
842 and byte [bs2Idt_BP + 5 xWrtRIP], 0e0h
843 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_UNDEFINED
844 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
845
846 ;
847 ; Make the IDTE not-present but otherwise fine, keeping CS invalid.
848 ;
849 and byte [bs2Idt_BP + 5 xWrtRIP], 070h
850%ifdef TMPL_LM64
851 or byte [bs2Idt_BP + 5 xWrtRIP], AMD64_SEL_TYPE_SYS_INT_GATE
852%else
853 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_TRAP_GATE
854%endif
855 BS2_TRAP_INSTR X86_XCPT_NP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
856
857 ;
858 ; Make the CS not present as well.
859 ;
860 and byte [bs2GdtSpare0 + 5 xWrtRIP], 070h
861 or byte [bs2GdtSpare0 + 5 xWrtRIP], X86_SEL_TYPE_EO
862 BS2_TRAP_INSTR X86_XCPT_NP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
863
864 ;
865 ; CS not present, IDTE invalid but present.
866 ;
867 and byte [bs2Idt_BP + 5 xWrtRIP], 0f0h
868 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_UNDEFINED | 0x80
869 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
870
871 ;
872 ; CS NULL, IDTE invalid but present.
873 ;
874 mov word [bs2Idt_BP + 2 xWrtRIP], 0
875 BS2_TRAP_INSTR X86_XCPT_GP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
876
877 ;
878 ; CS NULL, IDTE valid but not present.
879 ;
880 and byte [bs2Idt_BP + 5 xWrtRIP], 070h
881%ifdef TMPL_LM64
882 or byte [bs2Idt_BP + 5 xWrtRIP], AMD64_SEL_TYPE_SYS_INT_GATE
883%else
884 or byte [bs2Idt_BP + 5 xWrtRIP], X86_SEL_TYPE_SYS_386_TRAP_GATE
885%endif
886 BS2_TRAP_INSTR X86_XCPT_NP, (3 << X86_TRAP_ERR_SEL_SHIFT) | X86_TRAP_ERR_IDT, int3
887
888 ;
889 ; Restore the descriptor and make sure it works.
890 ;
891%ifdef TMPL_LM64
892 pop qword [bs2Idt_BP + 8 xWrtRIP]
893 pop qword [bs2Idt_BP xWrtRIP]
894%else
895 pop dword [bs2Idt_BP + 4 xWrtRIP]
896 pop dword [bs2Idt_BP xWrtRIP]
897%endif
898 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
899
900 ;
901 ; Done.
902 ;
903 call TMPL_NM_CMN(TestSubDone)
904
905 pop xSI
906 pop xDI
907 pop xDX
908 pop xCX
909 pop xBX
910 pop sAX
911 leave
912 ret
913
914.s_szSubTestName:
915 db TMPL_MODE_STR, ', IDTE.type before CS.type', 0
916ENDPROC TMPL_NM(TestCheckOrderCsTypeVsIdteType)
917
918
919;;
920; Checks stack switching behavior.
921;
922; @uses none
923;
924BEGINPROC TMPL_NM(TestStack)
925 push xBP
926 mov xBP, xSP
927 push sAX
928 push xBX
929 push xCX
930 push xDX
931 push xDI
932 push xSI
933 pushf
934 cli
935
936 mov xAX, .s_szSubTestName
937 call TMPL_NM_CMN(TestSub)
938
939
940 ;
941 ; Check the int3, save its IDTE, then make it ring-3 accessible.
942 ;
943 ; X86DESCGENERIC.u2Dpl is at bit 0x2d (i.e. in byte 5).
944 ;
945 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check that int3 works before we start messing around...
946
947%ifdef TMPL_LM64
948 push qword [bs2Idt_BP xWrtRIP]
949 push qword [bs2Idt_BP + 8 xWrtRIP]
950%else
951 push dword [bs2Idt_BP xWrtRIP]
952 push dword [bs2Idt_BP + 4 xWrtRIP]
953%endif
954
955 and byte [bs2Idt_BP + 5 xWrtRIP], ~(RT_BIT(5) | RT_BIT(6))
956 or byte [bs2Idt_BP + 5 xWrtRIP], 3 << 5 ; DPL == 3
957
958 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
959
960
961 ;
962 ; In ring-0 no stack switching is performed.
963 ;
964 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
965 mov xBX, [g_u64LastTrapHandlerRSP]
966%ifdef TMPL_64BIT
967 mov rax, rsp
968 and rax, ~15
969 sub rax, 7*8
970%else
971 lea eax, [esp - 5*4]
972%endif
973 ASSERT_SIMPLE sAX, xBX, je, "Wrong xSP value for ring-0 -> ring-0 int3."
974 mov bx, [g_u16LastTrapHandlerSS]
975 mov ax, ss
976 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-0 -> ring-0 int3."
977
978 ;
979 ; Switch to ring-1 and watch stack switching take place.
980 ;
981 call TMPL_NM_CMN(Bs2ToRing1)
982
983 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
984 mov xBX, [g_u64LastTrapHandlerRSP]
985 mov sAX, BS2_R0_STACK_ADDR
986%ifdef TMPL_64BIT
987 and rax, ~15
988 sub rax, 7*8
989%else
990 sub eax, 7*4
991%endif
992 ASSERT_SIMPLE sAX, xBX, je, "Wrong xSP value for ring-1 -> ring-0 int3."
993 mov bx, [g_u16LastTrapHandlerSS]
994%ifdef TMPL_64BIT
995 mov ax, 0
996%else
997 mov ax, MY_R0_SS
998%endif
999 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-1 -> ring-0 int3."
1000
1001 call TMPL_NM_CMN(Bs2ToRing0)
1002
1003 ;
1004 ; Missaligned stack, ring-0 -> ring-0.
1005 ;
1006 mov xDI, xSP ; save the stack pointer.
1007%rep 15
1008 sub xSP, 1h
1009
1010 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1011 mov xBX, [g_u64LastTrapHandlerRSP]
1012%ifdef TMPL_64BIT
1013 mov rax, rsp
1014 and rax, ~15
1015 sub rax, 7*8
1016%else
1017 lea eax, [esp - 5*4]
1018%endif
1019 ASSERT_SIMPLE sAX, xBX, je, "Wrong xSP value for ring-0 -> ring-0 int3, w/ unaligned stack."
1020 mov bx, [g_u16LastTrapHandlerSS]
1021 mov ax, ss
1022 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-0 -> ring-0 int3, w/ unaligned stack."
1023
1024%endrep
1025 mov xSP, xDI ; restore the stack pointer.
1026
1027 ;
1028 ; Missaligned stack, ring-1 -> ring-0.
1029 ;
1030 call TMPL_NM_CMN(Bs2ToRing1)
1031
1032 mov sSI, BS2_R0_STACK_ADDR - 16
1033%rep 16
1034 add sSI, 1
1035%ifdef TMPL_64BIT
1036 mov [bs2Tss64Bit + 4], sSI
1037%else
1038 mov [bs2Tss32Bit + 4], sSI
1039%endif
1040
1041 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1042 mov xBX, [g_u64LastTrapHandlerRSP]
1043 mov sAX, sSI
1044%ifdef TMPL_64BIT
1045 and rax, ~15
1046 sub rax, 7*8
1047%else
1048 sub eax, 7*4
1049%endif
1050 ASSERT_SIMPLE sAX, xBX, je, "Wrong xSP value for ring-1 -> ring-0 int3, w/ unaligned ring-0 stack."
1051 mov bx, [g_u16LastTrapHandlerSS]
1052%ifdef TMPL_64BIT
1053 mov ax, 0
1054%else
1055 mov ax, MY_R0_SS
1056%endif
1057 ASSERT_SIMPLE sAX, xBX, je, "Wrong SS value for ring-1 -> ring-0 int3, w/ unaligned ring-0 stack."
1058
1059%endrep
1060 call TMPL_NM_CMN(Bs2ToRing0)
1061
1062
1063%ifdef TMPL_64BIT
1064 ;
1065 ; Stack table (AMD64 only), ring-0 -> ring-0.
1066 ;
1067 and byte [bs2Idt_BP + 4], ~7
1068 or byte [bs2Idt_BP + 4], 3 ; IDTE.IST=3
1069
1070 mov rdi, [bs2Tss64Bit + X86TSS64.ist3]
1071 mov rsi, BS2_R0_STACK_ADDR - 128
1072 %rep 16
1073 sub rsi, 1h
1074 mov [bs2Tss64Bit + X86TSS64.ist3], rsi
1075
1076 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1077 mov rbx, [g_u64LastTrapHandlerRSP]
1078 mov rax, rsi
1079 and rax, ~15
1080 sub rax, 7*8
1081 ASSERT_SIMPLE rax, rbx, je, "Wrong xSP value for ring-0 -> ring-0 int3, w/ unaligned IST."
1082 mov bx, [g_u16LastTrapHandlerSS]
1083 mov ax, ss
1084 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-0 -> ring-0 int3, w/ unaligned IST."
1085
1086 %endrep
1087
1088 ; Continue in ring-1,2,3.
1089 %assign uCurRing 1
1090 %rep 3
1091 call TMPL_NM_CMN(Bs2ToRing %+ uCurRing)
1092 %rep 16
1093 sub rsi, 1h
1094 mov [bs2Tss64Bit + X86TSS64.ist3], rsi
1095
1096 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1097 mov rbx, [g_u64LastTrapHandlerRSP]
1098 mov rax, rsi
1099 and rax, ~15
1100 sub rax, 7*8
1101 ASSERT_SIMPLE rax, rbx, je, "Wrong xSP value for ring-X -> ring-0 int3, w/ unaligned IST."
1102 mov bx, [g_u16LastTrapHandlerSS]
1103 mov ax, 0
1104 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-X -> ring-0 int3, w/ unaligned IST."
1105 %endrep
1106 call TMPL_NM_CMN(Bs2ToRing0)
1107 %assign uCurRing (uCurRing + 1)
1108 %endrep
1109
1110 mov [bs2Tss64Bit + X86TSS64.ist3], rdi ; restore original value
1111 and byte [bs2Idt_BP + 4], ~7 ; IDTE.IST=0
1112
1113
1114 ;
1115 ; Check SS handling when interrupting 32-bit code with a 64-bit handler.
1116 ;
1117 call Bs2Thunk_lm64_lm32
1118 BITS 32
1119 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1120 mov bx, [g_u16LastTrapHandlerSS]
1121 mov ax, ss
1122 call Bs2Thunk_lm32_lm64
1123 BITS 64
1124 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-0-32 -> ring-0-64 int3, w/ 32-bit stack."
1125
1126 call Bs2Thunk_lm64_lm32
1127 BITS 32
1128 mov cx, ss
1129 mov ax, BS2_SEL_SS16
1130 mov ss, ax
1131 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1132 mov bx, [g_u16LastTrapHandlerSS]
1133 mov ss, cx
1134 call Bs2Thunk_lm32_lm64
1135 BITS 64
1136 ASSERT_SIMPLE ax, bx, je, "Wrong SS value for ring-0-32 -> ring-0-64 int3, w/ 16-bit stack."
1137
1138%endif ; TMPL_64BIT
1139
1140
1141 ;
1142 ; Restore the descriptor and make sure it works.
1143 ;
1144%ifdef TMPL_LM64
1145 pop qword [bs2Idt_BP + 8 xWrtRIP]
1146 pop qword [bs2Idt_BP xWrtRIP]
1147%else
1148 pop dword [bs2Idt_BP + 4 xWrtRIP]
1149 pop dword [bs2Idt_BP xWrtRIP]
1150%endif
1151 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1152
1153 ;
1154 ; Done.
1155 ;
1156 call TMPL_NM_CMN(TestSubDone)
1157
1158 popf
1159 pop xSI
1160 pop xDI
1161 pop xDX
1162 pop xCX
1163 pop xBX
1164 pop sAX
1165 leave
1166 ret
1167
1168.s_szSubTestName:
1169 db TMPL_MODE_STR, ', Stack switching', 0
1170ENDPROC TMPL_NM(TestStack)
1171
1172
1173
1174;;
1175; Loads MY_R0_CS into CS.
1176;
1177; @uses stack, cs, flags
1178;
1179BEGINPROC TMPL_NM(TestLoadMyCS)
1180 push 0
1181 push xAX
1182
1183 ; Make it a far return with MY_R0_CS + CPL.
1184 mov xAX, [xSP + xCB*2]
1185 mov [xSP + xCB*1], xAX
1186 mov xAX, ss
1187%ifdef TMPL_64BIT
1188 sub xAX, BS2_SEL_GRP_SS64 - BS2_SEL_GRP_CS64
1189%elifdef TMPL_32BIT
1190 sub xAX, BS2_SEL_GRP_SS32 - BS2_SEL_GRP_CS32
1191%elifdef TMPL_16BIT
1192 sub xAX, BS2_SEL_GRP_SS16 - BS2_SEL_GRP_CS16
1193%else
1194 TMPL_xxBIT is not defined
1195%endif
1196 mov [xSP + xCB*2], xAX
1197
1198 pop xAX
1199 retf
1200ENDPROC TMPL_NM(TestLoadMyCS)
1201
1202
1203;;
1204; Checks our understanding of how conforming segments are handled.
1205;
1206; @uses No registers, but BS2_SEL_SPARE0 is trashed.
1207;
1208BEGINPROC TMPL_NM(TestConforming)
1209 push xBP
1210 mov xBP, xSP
1211 push sAX
1212 push xBX
1213 push xCX
1214 push xDX
1215 push xDI
1216 push xSI
1217
1218 mov xAX, .s_szSubTestName
1219 call TMPL_NM_CMN(TestSub)
1220
1221 ;
1222 ; Check the int3.
1223 ;
1224 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3 ; check that int3 works before we start messing around...
1225
1226 mov xDI, xSP ; save the stack pointer.
1227 sub xSP, 20h
1228
1229 ;
1230 ; In this test we will do various experiments with code using a
1231 ; conforming CS. The main purpose is to check that CS.RPL is always the
1232 ; same as CPL, despite earlier beliefs to the contrary. Because if it
1233 ; is different, iret cannot dermine the CPL to return to among other
1234 ; interesting problems.
1235 ;
1236 mov ecx, [bs2Gdt + MY_R0_CS xWrtRIP]
1237 mov [bs2GdtSpare0 xWrtRIP], ecx
1238 mov ecx, [bs2Gdt + MY_R0_CS + 4 xWrtRIP]
1239 mov [bs2GdtSpare0 + 4 xWrtRIP], ecx ; GdtSpare0 is a copy of the CS descriptor now.
1240 and byte [bs2GdtSpare0 + 5], 0x90 ; DPL = 0
1241 or byte [bs2GdtSpare0 + 5], X86_SEL_TYPE_ER_CONF_ACC
1242
1243%assign uCurRing 0
1244%rep 4
1245 ; Far jumps.
1246 %assign uSpecifiedRpl 0
1247 %rep 4
1248 call TMPL_NM_CMN(Bs2ToRing %+ uCurRing)
1249 lea xAX, [.far_jmp_target_ %+ uSpecifiedRpl %+ uCurRing]
1250 %ifdef TMPL_64BIT ; AMD doesn't have an jmp far m16:m64 instruction, it ignores REX.W apparently. Intel does though.
1251 ; Tested on: Bulldozer
1252 mov dword [xSP + 4], BS2_SEL_SPARE0 | uSpecifiedRpl
1253 mov [xSP], eax
1254 jmp far dword [xSP]
1255 %else
1256 mov dword [xSP + xCB], BS2_SEL_SPARE0 | uSpecifiedRpl
1257 mov [xSP], xAX
1258 jmp far xPRE [xSP]
1259 %endif
1260.far_jmp_target_ %+ uSpecifiedRpl %+ uCurRing:
1261 mov bx, cs
1262 call TMPL_NM(TestLoadMyCS)
1263 call TMPL_NM_CMN(Bs2ToRing0)
1264 ASSERT_CUR_CS_VALUE_IN_BX BS2_SEL_SPARE0 | uCurRing
1265 %assign uSpecifiedRpl uSpecifiedRpl + 1
1266 %endrep
1267
1268 ; Far calls.
1269 %assign uSpecifiedRpl 0
1270 %rep 4
1271 call TMPL_NM_CMN(Bs2ToRing %+ uCurRing)
1272 mov xSI, xSP
1273 lea xAX, [.far_call_target_ %+ uSpecifiedRpl %+ uCurRing]
1274 %ifdef TMPL_64BIT ; AMD doesn't have an call far m16:m64 instruction, it ignores REX.W apparently. Intel does though.
1275 ; Tested on: Bulldozer
1276 mov dword [xSP + 4], BS2_SEL_SPARE0 | uSpecifiedRpl
1277 mov [xSP], eax
1278 call far dword [xSP]
1279 %else
1280 mov dword [xSP + xCB], BS2_SEL_SPARE0 | uSpecifiedRpl
1281 mov [xSP], xAX
1282 call far xPRE [xSP]
1283 %endif
1284.far_call_target_ %+ uSpecifiedRpl %+ uCurRing:
1285 mov bx, cs
1286 %ifdef TMPL_64BIT
1287 add xSP, 4 * 2
1288 %else
1289 add xSP, xCB * 2
1290 %endif
1291 call TMPL_NM(TestLoadMyCS)
1292 call TMPL_NM_CMN(Bs2ToRing0)
1293 ASSERT_CUR_CS_VALUE_IN_BX BS2_SEL_SPARE0 | uCurRing
1294 %assign uSpecifiedRpl uSpecifiedRpl + 1
1295 %endrep
1296
1297 %assign uCurRing uCurRing + 1
1298%endrep
1299
1300 ;
1301 ; While at it, lets check something about RPL and non-conforming
1302 ; segments. The check when loading is supposed to be RPL >= DPL,
1303 ; except for when loading SS, where RPL = DPL = CPL.
1304 ;
1305
1306 ; ring-0
1307 mov dx, MY_R0_DS | 0
1308 mov fs, dx
1309 ASSERT_CUR_SREG_VALUE fs, MY_R0_DS | 0
1310 mov dx, MY_R0_DS | 1
1311 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1312 mov dx, MY_R0_DS | 2
1313 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1314 mov dx, MY_R0_DS | 3
1315 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1316
1317 ; ring-0 - Lower DPL isn't an issue, only RPL vs DPL.
1318 mov dx, MY_R1_DS | 0
1319 mov fs, dx
1320 ASSERT_CUR_SREG_VALUE fs, MY_R1_DS | 0
1321 mov dx, MY_R1_DS | 1
1322 mov fs, dx
1323 ASSERT_CUR_SREG_VALUE fs, MY_R1_DS | 1
1324 mov dx, MY_R1_DS | 2
1325 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1326
1327 mov dx, MY_R2_DS | 0
1328 mov fs, dx
1329 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 0
1330 mov dx, MY_R2_DS | 2
1331 mov fs, dx
1332 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 2
1333 mov dx, MY_R2_DS | 3
1334 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1335
1336 mov dx, MY_R3_DS | 0
1337 mov fs, dx
1338 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 0
1339 mov dx, MY_R3_DS | 1
1340 mov fs, dx
1341 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 1
1342 mov dx, MY_R3_DS | 2
1343 mov fs, dx
1344 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 2
1345 mov dx, MY_R3_DS | 3
1346 mov fs, dx
1347 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 3
1348
1349 ; ring-0 - What works above doesn't work with ss.
1350 mov dx, MY_R1_DS | 0
1351 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov ss, dx
1352 mov dx, MY_R1_DS | 1
1353 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov ss, dx
1354 mov dx, MY_R1_DS | 2
1355 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov ss, dx
1356 mov dx, MY_R2_DS | 0
1357 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov ss, dx
1358 mov dx, MY_R3_DS | 0
1359 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1360 mov dx, MY_R3_DS | 3
1361 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1362
1363
1364 ; ring-1
1365 call TMPL_NM_CMN(Bs2ToRing1)
1366
1367 mov dx, MY_R1_DS | 0
1368 mov fs, dx
1369 ASSERT_CUR_SREG_VALUE fs, MY_R1_DS | 0
1370 mov dx, MY_R1_DS | 1
1371 mov fs, dx
1372 ASSERT_CUR_SREG_VALUE fs, MY_R1_DS | 1
1373 mov dx, MY_R1_DS | 2
1374 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1375 mov dx, MY_R1_DS | 3
1376 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1377
1378 mov dx, MY_R0_DS | 0
1379 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1380 mov dx, MY_R0_DS | 1
1381 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1382 mov dx, MY_R0_DS | 2
1383 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1384 mov dx, MY_R0_DS | 3
1385 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1386
1387 ; ring-1 - Lower DPL isn't an issue, only RPL vs DPL.
1388 mov dx, MY_R2_DS | 0
1389 mov fs, dx
1390 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 0
1391 mov dx, MY_R2_DS | 1
1392 mov fs, dx
1393 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 1
1394 mov dx, MY_R2_DS | 2
1395 mov fs, dx
1396 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 2
1397 mov dx, MY_R2_DS | 3
1398 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1399
1400 mov dx, MY_R3_DS | 0
1401 mov fs, dx
1402 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 0
1403 mov dx, MY_R3_DS | 1
1404 mov fs, dx
1405 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 1
1406 mov dx, MY_R3_DS | 2
1407 mov fs, dx
1408 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 2
1409 mov dx, MY_R3_DS | 3
1410 mov fs, dx
1411 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 3
1412
1413 ; ring-1 - What works above doesn't work with ss.
1414 mov dx, MY_R1_DS | 0
1415 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov ss, dx
1416 mov dx, MY_R1_DS | 2
1417 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov ss, dx
1418 mov dx, MY_R2_DS | 0
1419 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov ss, dx
1420 mov dx, MY_R3_DS | 0
1421 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1422 mov dx, MY_R3_DS | 3
1423 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1424
1425
1426 ; ring-2
1427 call TMPL_NM_CMN(Bs2ToRing2)
1428
1429 mov dx, MY_R2_DS | 0
1430 mov fs, dx
1431 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 0
1432 mov dx, MY_R2_DS | 1
1433 mov fs, dx
1434 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 1
1435 mov dx, MY_R2_DS | 2
1436 mov fs, dx
1437 ASSERT_CUR_SREG_VALUE fs, MY_R2_DS | 2
1438 mov dx, MY_R2_DS | 3
1439 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1440
1441 mov dx, MY_R0_DS | 0
1442 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1443 mov dx, MY_R0_DS | 1
1444 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1445 mov dx, MY_R0_DS | 2
1446 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1447 mov dx, MY_R0_DS | 3
1448 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1449 mov dx, MY_R1_DS | 1
1450 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1451 mov dx, MY_R1_DS | 2
1452 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1453
1454 ; ring-2 - Lower DPL isn't an issue, only RPL vs DPL.
1455 mov dx, MY_R3_DS | 0
1456 mov fs, dx
1457 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 0
1458 mov dx, MY_R3_DS | 1
1459 mov fs, dx
1460 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 1
1461 mov dx, MY_R3_DS | 2
1462 mov fs, dx
1463 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 2
1464 mov dx, MY_R3_DS | 3
1465 mov fs, dx
1466 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 3
1467
1468 ; ring-2 - What works above doesn't work with ss.
1469 mov dx, MY_R2_DS | 1
1470 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov ss, dx
1471 mov dx, MY_R2_DS | 3
1472 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov ss, dx
1473 mov dx, MY_R3_DS | 0
1474 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1475 mov dx, MY_R3_DS | 1
1476 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1477 mov dx, MY_R3_DS | 2
1478 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1479 mov dx, MY_R3_DS | 3
1480 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1481
1482
1483 ; ring-3
1484 call TMPL_NM_CMN(Bs2ToRing3)
1485
1486 mov dx, MY_R3_DS | 0
1487 mov fs, dx
1488 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 0
1489 mov dx, MY_R3_DS | 1
1490 mov fs, dx
1491 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 1
1492 mov dx, MY_R3_DS | 2
1493 mov fs, dx
1494 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 2
1495 mov dx, MY_R3_DS | 3
1496 mov fs, dx
1497 ASSERT_CUR_SREG_VALUE fs, MY_R3_DS | 3
1498
1499 mov dx, MY_R0_DS | 0
1500 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1501 mov dx, MY_R0_DS | 1
1502 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1503 mov dx, MY_R0_DS | 2
1504 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1505 mov dx, MY_R0_DS | 3
1506 BS2_TRAP_INSTR X86_XCPT_GP, MY_R0_DS, mov fs, dx
1507
1508 mov dx, MY_R1_DS | 1
1509 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1510 mov dx, MY_R1_DS | 2
1511 BS2_TRAP_INSTR X86_XCPT_GP, MY_R1_DS, mov fs, dx
1512
1513 mov dx, MY_R2_DS | 0
1514 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1515 mov dx, MY_R2_DS | 1
1516 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1517 mov dx, MY_R2_DS | 2
1518 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1519 mov dx, MY_R2_DS | 3
1520 BS2_TRAP_INSTR X86_XCPT_GP, MY_R2_DS, mov fs, dx
1521
1522 ; ring-0 - What works above doesn't work with ss.
1523 mov dx, MY_R3_DS | 0
1524 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1525 mov dx, MY_R3_DS | 1
1526 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1527 mov dx, MY_R3_DS | 2
1528 BS2_TRAP_INSTR X86_XCPT_GP, MY_R3_DS, mov ss, dx
1529
1530 call TMPL_NM_CMN(Bs2ToRing0)
1531
1532
1533 ;
1534 ; One more odd thing, NULL selectors and RPL.
1535 ;
1536 pushf
1537 cli
1538
1539%assign uCurRing 0
1540%rep 4
1541 ; Null sectors.
1542 call TMPL_NM_CMN(Bs2ToRing %+ uCurRing)
1543 mov si, ss
1544
1545 mov dx, 0
1546 mov fs, dx
1547 ASSERT_CUR_SREG_VALUE fs, 0
1548 %if MY_IS_64BIT == 0 || uCurRing != 0
1549 %ifdef TMPL_64BIT ; AMD is doing something inconsistent.
1550 %if uCurRing != 3
1551 test byte [g_fCpuAmd], 1
1552 jz .null_0_not_amd_ %+ uCurRing
1553 mov ss, dx
1554 ASSERT_CUR_SREG_VALUE ss, 0
1555 jmp .null_0_next_ %+ uCurRing
1556.null_0_not_amd_ %+ uCurRing:
1557 %endif
1558 %endif
1559 BS2_TRAP_INSTR X86_XCPT_GP, 0, mov ss, dx
1560.null_0_next_ %+ uCurRing:
1561 %else
1562 mov ss, dx
1563 ASSERT_CUR_SREG_VALUE ss, 0
1564 %endif
1565 mov ss, si
1566
1567 mov dx, 1
1568 mov fs, dx
1569 ASSERT_CUR_SREG_VALUE fs, 1
1570 %if MY_IS_64BIT == 0 || uCurRing != 1
1571 %ifdef TMPL_64BIT ; AMD is doing something inconsistent.
1572 %if uCurRing != 3
1573 test byte [g_fCpuAmd], 1
1574 jz .null_1_not_amd_ %+ uCurRing
1575 mov ss, dx
1576 ASSERT_CUR_SREG_VALUE ss, 1
1577 jmp .null_1_next_ %+ uCurRing
1578.null_1_not_amd_ %+ uCurRing:
1579 %endif
1580 %endif
1581 BS2_TRAP_INSTR X86_XCPT_GP, 0, mov ss, dx
1582.null_1_next_ %+ uCurRing:
1583 %else
1584 mov ss, dx
1585 ASSERT_CUR_SREG_VALUE ss, 1
1586 %endif
1587 mov ss, si
1588
1589 mov dx, 2
1590 mov fs, dx
1591 ASSERT_CUR_SREG_VALUE fs, 2
1592 %if MY_IS_64BIT == 0 || uCurRing != 2
1593 %ifdef TMPL_64BIT ; AMD is doing something inconsistent.
1594 %if uCurRing != 3
1595 test byte [g_fCpuAmd], 1
1596 jz .null_2_not_amd_ %+ uCurRing
1597 mov ss, dx
1598 ASSERT_CUR_SREG_VALUE ss, 2
1599 jmp .null_2_next_ %+ uCurRing
1600.null_2_not_amd_ %+ uCurRing:
1601 %endif
1602 %endif
1603 BS2_TRAP_INSTR X86_XCPT_GP, 0, mov ss, dx
1604.null_2_next_ %+ uCurRing:
1605 %else
1606 mov ss, dx
1607 ASSERT_CUR_SREG_VALUE ss, 2
1608 %endif
1609 mov ss, si
1610
1611 mov dx, 3
1612 mov fs, dx
1613 ASSERT_CUR_SREG_VALUE fs, 3
1614 %ifdef TMPL_64BIT ; AMD is doing something inconsistent.
1615 %if uCurRing != 3
1616 test byte [g_fCpuAmd], 1
1617 jz .null_3_not_amd_ %+ uCurRing
1618 mov ss, dx
1619 ASSERT_CUR_SREG_VALUE ss, 3
1620 jmp .null_3_next_ %+ uCurRing
1621.null_3_not_amd_ %+ uCurRing:
1622 %endif
1623 %endif
1624 BS2_TRAP_INSTR X86_XCPT_GP, 0, mov ss, dx
1625.null_3_next_ %+ uCurRing:
1626 mov ss, si
1627
1628 %assign uCurRing uCurRing + 1
1629%endrep
1630 call TMPL_NM_CMN(Bs2ToRing0)
1631
1632 ; Restore the selectors.
1633 mov dx, MY_R0_DS
1634 mov ds, dx
1635 mov es, dx
1636 mov fs, dx
1637 mov gs, dx
1638 popf
1639
1640
1641 ;
1642 ; Restore the descriptor and make sure it works.
1643 ;
1644 mov xSP, xDI ; restore the stack pointer.
1645 BS2_TRAP_INSTR X86_XCPT_BP, 0, int3
1646
1647 ;
1648 ; Done.
1649 ;
1650 call TMPL_NM_CMN(TestSubDone)
1651
1652 pop xSI
1653 pop xDI
1654 pop xDX
1655 pop xCX
1656 pop xBX
1657 pop sAX
1658 leave
1659 ret
1660
1661.s_szSubTestName:
1662 db TMPL_MODE_STR, ', Conforming CS, ++', 0
1663ENDPROC TMPL_NM(TestConforming)
1664
1665
1666
1667;;
1668; Returning from interrupt/trap/whatever handlers.
1669;
1670; @uses No registers, but BS2_SEL_SPARE0 is trashed.
1671;
1672BEGINPROC TMPL_NM(TestReturn)
1673 push xBP
1674 mov xBP, xSP
1675 push sAX
1676 push xBX
1677 push xCX
1678 push xDX
1679 push xDI
1680 push xSI
1681 sub xSP, 80h ; iret stack frame space.
1682 mov xSI, xSP ; Save the stack register.
1683
1684 mov xAX, .s_szSubTestName
1685 call TMPL_NM_CMN(TestSub)
1686
1687%ifdef TMPL_64BIT
1688 pushfq
1689 pop rdi ; rdi contains good flags register value.
1690
1691 ;
1692 ; 64-bit mode: IRETQ unconditional pop of SS:RSP.
1693 ;
1694 mov qword [rsp + 20h], MY_R0_SS
1695 mov [rsp + 18h], rsp
1696 mov [rsp + 10h], rdi
1697 mov qword [rsp + 08h], MY_R0_CS
1698 lea rax, [.resume1 wrt rip]
1699 mov [rsp + 00h], rax
1700 iretq
1701
1702.resume1:
1703 pushfq
1704 pop rbx
1705 ASSERT_SIMPLE rsp, rsi, je, "Wrong RSP after IRETQ."
1706 mov rsp, rsi
1707 ASSERT_SIMPLE rbx, rdi, je, "Wrong flags after IRETQ."
1708 mov ax, ss
1709 ASSERT_SIMPLE ax, MY_R0_SS, je, "Wrong SS after IRETQ."
1710 mov ax, cs
1711 ASSERT_SIMPLE ax, MY_R0_CS, je, "Wrong CS after IRETQ."
1712
1713 ; 64-bit mode: The NT flag causes #GP(0)
1714 mov qword [rsp + 20h], MY_R0_SS
1715 lea rax, [rsp - 100h]
1716 mov [rsp + 18h], rax
1717 mov [rsp + 10h], rdi
1718 mov qword [rsp + 08h], MY_R0_CS
1719 lea rax, [.resume2 wrt rip]
1720 mov [rsp + 00h], rax
1721 push rdi
1722 or dword [rsp], X86_EFL_NT
1723 popfq
1724 BS2_TRAP_BRANCH_INSTR X86_XCPT_GP, 0, .resume2, iretq
1725 pushfq
1726 pop rbx
1727 push rdi
1728 popfq
1729 ASSERT_SIMPLE rsp, rsi, je, "Wrong RSP after IRETQ."
1730 mov rsp, rsi
1731 mov rax, rdi
1732 or rax, X86_EFL_NT
1733 ASSERT_SIMPLE rbx, rax, je, "Wrong flags after IRETQ GP(0)-NT."
1734 mov ax, ss
1735 ASSERT_SIMPLE ax, MY_R0_SS, je, "Wrong SS after IRETQ."
1736 mov ax, cs
1737 ASSERT_SIMPLE ax, MY_R0_CS, je, "Wrong CS after IRETQ."
1738
1739 ; 64-bit mode: The VM flag is disregarded.
1740 mov qword [rsp + 20h], MY_R0_SS
1741 lea rax, [rsp - 88h]
1742 mov [rsp + 18h], rax
1743 mov [rsp + 10h], rdi
1744 or dword [rsp + 10h], X86_EFL_VM
1745 mov qword [rsp + 08h], MY_R0_CS
1746 lea rax, [.resume3 wrt rip]
1747 mov [rsp + 00h], rax
1748 iretq
1749.resume3:
1750 pushfq
1751 pop rbx
1752 add rsp, 88h
1753 ASSERT_SIMPLE rsp, rsi, je, "Wrong RSP after IRETQ."
1754 mov rsp, rsi
1755 mov rax, rdi
1756 ASSERT_SIMPLE rbx, rax, je, "Wrong flags after IRETQ GP(0)-NT."
1757 mov ax, ss
1758 ASSERT_SIMPLE ax, MY_R0_SS, je, "Wrong SS after IRETQ."
1759 mov ax, cs
1760 ASSERT_SIMPLE ax, MY_R0_CS, je, "Wrong CS after IRETQ."
1761
1762 ;
1763 ; 64-bit mode: IRETD unconditionally pops SS:ESP as well.
1764 ;
1765 mov dword [rsp + 10h], MY_R0_SS
1766 lea eax, [esp - 18h]
1767 mov [rsp + 0ch], eax
1768 mov [rsp + 08h], edi
1769 mov dword [rsp + 04h], MY_R0_CS
1770 lea eax, [.resume20 wrt rip]
1771 mov [rsp + 00h], eax
1772 iretd
1773.resume20:
1774 pushfq
1775 pop rbx
1776 add rsp, 18h
1777 ASSERT_SIMPLE rsp, rsi, je, "Wrong RSP after IRETD."
1778 mov rsp, rsi
1779 ASSERT_SIMPLE rbx, rdi, je, "Wrong flags after IRETD."
1780 mov ax, ss
1781 ASSERT_SIMPLE ax, MY_R0_SS, je, "Wrong SS after IRETD."
1782 mov ax, cs
1783 ASSERT_SIMPLE ax, MY_R0_CS, je, "Wrong CS after IRETD."
1784
1785 ;
1786 ; 64-bit mode: IRET unconditionally pops SS:SP as well.
1787 ;
1788 mov word [rsp + 08h], MY_R0_SS
1789 lea eax, [esp - 1ah]
1790 mov [rsp + 06h], ax
1791 mov [rsp + 04h], di
1792 mov word [rsp + 02h], MY_R0_CS
1793 mov word [rsp + 00h], .resume30
1794 o16 iret
1795BEGINCODELOW
1796.resume30:
1797 jmp .high1
1798BEGINCODEHIGH
1799.high1:
1800 pushfq
1801 pop rbx
1802 add rsp, 1ah
1803 ASSERT_SIMPLE rsp, rsi, je, "Wrong RSP after IRET."
1804 mov rsp, rsi
1805 ASSERT_SIMPLE rbx, rdi, je, "Wrong flags after IRET."
1806 mov ax, ss
1807 ASSERT_SIMPLE ax, MY_R0_SS, je, "Wrong SS after IRET."
1808 mov ax, cs
1809 ASSERT_SIMPLE ax, MY_R0_CS, je, "Wrong CS after IRET."
1810
1811
1812%elifdef TMPL_32BIT
1813 ; later...
1814%endif
1815
1816 ;
1817 ; Returning to 16-bit code, what happens to upper ESP bits?
1818 ;
1819 cli
1820 mov xBX, xSP ; save the current stack address
1821
1822 mov sAX, BS2_SEL_R3_SS16 | 3
1823 push sAX ; Return SS
1824 movzx edi, bx
1825 or edi, 0xdead0000
1826 push sDI ; Return sSP
1827%ifdef TMPL_64BIT
1828 pushfq
1829%else
1830 pushfd
1831%endif
1832 mov sAX, BS2_SEL_R3_CS16 | 3
1833 push sAX ; Return CS
1834 lea sAX, [.resume100 xWrtRIP]
1835 push sAX ; Return sIP
1836%ifdef TMPL_64BIT
1837 iretq
1838%else
1839 iretd
1840%endif
1841
1842BEGINCODELOW
1843BITS 16
1844.resume100:
1845 xchg ebx, esp
1846 call Bs2ToRing0_p16
1847 call TMPL_NM(Bs2Thunk_p16)
1848BITS TMPL_BITS
1849 jmp .high100
1850BEGINCODEHIGH
1851.high100:
1852 and edi, 0ffffh
1853 ASSERT_SIMPLE ebx, edi, je, "IRET to 16-bit didn't restore ESP as expected [#1]."
1854
1855%ifndef TMPL_16BIT
1856 ;
1857 ; Take two on 16-bit return, does the high word of ESP leak?
1858 ;
1859 cli
1860 mov sBX, sSP ; save the current stack address
1861 mov xSP, BS2_MUCK_ABOUT_BASE + 1000h
1862
1863 mov sAX, BS2_SEL_R3_SS16 | 3
1864 push sAX ; Return SS
1865 mov sDI, sBX
1866 push sDI ; Return sSP
1867 %ifdef TMPL_64BIT
1868 pushfq
1869 %else
1870 pushfd
1871 %endif
1872 mov sAX, BS2_SEL_R3_CS16 | 3
1873 push sAX ; Return CS
1874 lea sAX, [.resume101 xWrtRIP]
1875 push sAX ; Return sIP
1876 %ifdef TMPL_64BIT
1877 iretq
1878 %else
1879 iretd
1880 %endif
1881
1882BEGINCODELOW
1883BITS 16
1884.resume101:
1885 xchg ebx, esp
1886 call Bs2ToRing0_p16
1887 call TMPL_NM(Bs2Thunk_p16)
1888BITS TMPL_BITS
1889 jmp .high101
1890BEGINCODEHIGH
1891.high101:
1892 or edi, (BS2_MUCK_ABOUT_BASE + 1000h) & 0ffff0000h
1893 ASSERT_SIMPLE ebx, edi, je, "IRET to 16-bit didn't restore ESP as expected [#2]."
1894%endif ; Not 16-bit.
1895
1896 ;
1897 ; Done.
1898 ;
1899 call TMPL_NM_CMN(TestSubDone)
1900
1901 mov xSP, xSI
1902 add xSP, 80h
1903 pop xSI
1904 pop xDI
1905 pop xDX
1906 pop xCX
1907 pop xBX
1908 pop sAX
1909 leave
1910 ret
1911
1912.s_szSubTestName:
1913 db TMPL_MODE_STR, ', IRET', 0
1914ENDPROC TMPL_NM(TestReturn)
1915
1916;;
1917; Do the tests for this mode.
1918;
1919; @uses nothing
1920;
1921BEGINCODELOW
1922BITS 16
1923BEGINPROC TMPL_NM(DoTestsForMode_rm)
1924 push bp
1925 mov bp, sp
1926 push ax
1927
1928 ;
1929 ; Check if the mode and NX is supported, do the switch.
1930 ;
1931 call TMPL_NM(Bs2IsModeSupported_rm)
1932 jz .done
1933 call TMPL_NM(Bs2EnterMode_rm)
1934BITS TMPL_BITS
1935
1936 ;
1937 ; Test exception handler basics using INT3 and #BP.
1938 ;
1939
1940 call TMPL_NM(TestGateType)
1941 call TMPL_NM(TestCodeSelector)
1942 call TMPL_NM(TestCheckOrderCsTypeVsIdteType)
1943 call TMPL_NM(TestStack)
1944 call TMPL_NM(TestConforming)
1945 call TMPL_NM(TestReturn)
1946
1947 ;
1948 ; Back to real mode.
1949 ;
1950 call TMPL_NM(Bs2ExitMode)
1951BITS 16
1952 call Bs2DisableNX_r86
1953
1954.done:
1955 pop ax
1956 leave
1957 ret
1958ENDPROC TMPL_NM(DoTestsForMode_rm)
1959TMPL_BEGINCODE
1960BITS TMPL_BITS
1961
1962%include "bootsector2-template-footer.mac"
1963
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette