VirtualBox

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

Last change on this file since 103068 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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