VirtualBox

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

最後變更 在這個檔案從97115是 97115,由 vboxsync 提交於 2 年 前

ValKit: Test how 32-bit CMPXCHG clears or doesn't clear high dwords of 64-bit registers.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.5 KB
 
1; $Id: bootsector2-cpu-instr-1-template.mac 97115 2022-10-12 14:24:37Z vboxsync $
2;; @file
3; Bootsector test for misc instruction - multi mode template.
4;
5
6;
7; Copyright (C) 2007-2022 Oracle and/or its affiliates.
8;
9; This file is part of VirtualBox base platform packages, as
10; available from https://www.alldomusa.eu.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;;
43; Memory fence instructions (SSE2).
44;
45; @uses No registers, but BS2_SEL_SPARE0 is trashed.
46;
47BEGINPROC TMPL_NM(TestMemFences)
48 push xBP
49 mov xBP, xSP
50 push sAX
51 push xBX
52 push xCX
53 push xDX
54 push xDI
55 push xSI
56 sub xSP, 80h ; iret stack frame space.
57 mov xSI, xSP ; Save the stack register.
58
59 mov xAX, .s_szSubTestName
60 call TMPL_NM_CMN(TestSub)
61
62 ;
63 ; SSE2 supported?
64 ;
65 mov eax, 1
66 xor ecx, ecx
67 cpuid
68 test edx, X86_CPUID_FEATURE_EDX_SSE2
69 jz .skip
70
71 ;
72 ; Check that the standard instruction encodings work.
73 ;
74 mov xBX, [xSP + 10h]
75 mov [xSP], xAX
76 mfence
77 mov [xSP], xCX
78 mov xBX, [xSP + 08h]
79 sfence
80 mov [xSP], xDX
81 mov xBX, [xSP]
82 lfence
83 mov bx, [xSP + 04h]
84
85
86 ;
87 ; The instruction encodings in the intel manual may open the RM as well
88 ; as prefixes open to interpretation. AMD sets RM=0 in their docs.
89 ;
90 ; lfence = 0f,ea,e8
91 ; mfence = 0f,ea,f0
92 ; sfence = 0f,ea,f8
93 ; (RM is the lower 3 bits of the last byte.)
94
95%assign MY_RM 0xe8
96%rep 18h
97 db 0fh, 0aeh, MY_RM
98 db X86_OP_PRF_CS, 0fh, 0aeh, MY_RM
99 db X86_OP_PRF_DS, 0fh, 0aeh, MY_RM
100 db X86_OP_PRF_ES, 0fh, 0aeh, MY_RM
101 db X86_OP_PRF_FS, 0fh, 0aeh, MY_RM
102 db X86_OP_PRF_GS, 0fh, 0aeh, MY_RM
103 db X86_OP_PRF_SS, 0fh, 0aeh, MY_RM
104 db X86_OP_PRF_SIZE_ADDR, 0fh, 0aeh, MY_RM
105 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_SIZE_OP, 0fh, 0aeh, MY_RM ; (used in group)
106 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_LOCK, 0fh, 0aeh, MY_RM ; (used in group)
107 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPNZ, 0fh, 0aeh, MY_RM ; (used in group)
108 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPZ, 0fh, 0aeh, MY_RM ; (used in group)
109%ifdef TMPL_64BIT
110 %assign MY_REX 0x40
111 %rep 10h
112 ; Rex prefixes doesn't change anything.
113 db MY_REX, 0fh, 0aeh, MY_RM
114 db X86_OP_PRF_CS, MY_REX, 0fh, 0aeh, MY_RM
115 db X86_OP_PRF_DS, MY_REX, 0fh, 0aeh, MY_RM
116 db X86_OP_PRF_ES, MY_REX, 0fh, 0aeh, MY_RM
117 db X86_OP_PRF_FS, MY_REX, 0fh, 0aeh, MY_RM
118 db X86_OP_PRF_GS, MY_REX, 0fh, 0aeh, MY_RM
119 db X86_OP_PRF_SS, MY_REX, 0fh, 0aeh, MY_RM
120 db X86_OP_PRF_SIZE_ADDR, MY_REX, 0fh, 0aeh, MY_RM
121 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_SIZE_OP, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
122 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_LOCK, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
123 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPNZ, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
124 BS2_TRAP_INSTR X86_XCPT_UD, 0, db X86_OP_PRF_REPZ, MY_REX, 0fh, 0aeh, MY_RM ; (used in group)
125 %assign MY_REX (MY_REX + 1)
126 %endrep
127%endif
128 %assign MY_RM (MY_RM + 1)
129%endrep
130
131 ;
132 ; Done.
133 ;
134 call TMPL_NM_CMN(TestSubDone)
135.done:
136 mov xSP, xSI
137 add xSP, 80h
138 pop xSI
139 pop xDI
140 pop xDX
141 pop xCX
142 pop xBX
143 pop sAX
144 leave
145 ret
146
147.skip:
148 mov xAX, .s_szSse2Missing
149 call TMPL_NM_CMN(TestSubDone)
150 jmp .done
151
152.s_szSubTestName:
153 db TMPL_MODE_STR, ', mfence et al.', 0
154.s_szSse2Missing:
155 db 'SSE2 is missing', 0
156ENDPROC TMPL_NM(TestMemFences)
157
158
159;;
160; Floating-point to integer conversion (SSE/SSE2).
161; Neither Intel nor AMD explicitly document what happens for the 32-bit forms
162; of CVTxx2SI in 64-bit mode with regard to the high dword of a 64-bit
163; destination register.
164;
165; @uses XMM0, and BS2_SEL_SPARE0 is trashed.
166;
167BEGINPROC TMPL_NM(TestCvtSize)
168 push xBP
169 mov xBP, xSP
170 push sAX
171 push xBX
172 push xCX
173 push xDX
174 push xDI
175 push xSI
176 sub xSP, 80h ; iret stack frame space.
177 mov xSI, xSP ; Save the stack register.
178
179 mov xAX, .s_szSubTestName
180 call TMPL_NM_CMN(TestSub)
181
182 ;
183 ; SSE2 supported?
184 ;
185 mov eax, 1
186 xor ecx, ecx
187 cpuid
188 test edx, X86_CPUID_FEATURE_EDX_SSE2
189 jz .skip
190
191%ifdef TMPL_64BIT
192
193 ;
194 ; Have to enable OSFXSR for SSE instructions to work.
195 ;
196 mov rcx,cr4
197 mov rsi,rcx
198 or rcx,200h
199 mov cr4,rcx
200
201 ;
202 ; Load 32-bit float -2.75 into XMM0
203 ;
204 mov eax, 0C0300000h
205 movd xmm0, eax
206 mov rbx, -1 ; make sure high dword is not zero
207 cvtss2si ebx, xmm0 ; result is -3
208 mov eax, -3 ; high dword of rax zeroed
209 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTSS2SI EBX"
210
211 mov eax, 0C0300000h
212 movd xmm0, eax
213 mov rbx, -1
214 cvttss2si ebx, xmm0 ; result is -2
215 mov eax, -2
216 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTTSS2SI EBX"
217
218 ;
219 ; Load 64-bit double -2.75 into XMM0
220 ;
221 mov rax, 0C006000000000000h
222 movd xmm0, rax
223 mov rbx, -1
224 cvtsd2si ebx, xmm0
225 mov eax, -3
226 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTSD2SI EBX"
227
228 mov rax, 0C006000000000000h
229 mov rbx, -1
230 movd xmm0, rax
231 cvttsd2si ebx, xmm0
232 mov eax,-2
233 TEST_ASSERT_SIMPLE rbx, rax, jz, "CVTTSD2SI EBX"
234
235 ;
236 ; Restore prior CR4 value
237 ;
238 mov cr4,rsi
239%endif
240
241 ;
242 ; Done.
243 ;
244 call TMPL_NM_CMN(TestSubDone)
245.done:
246 mov xSP, xSI
247 add xSP, 80h
248 pop xSI
249 pop xDI
250 pop xDX
251 pop xCX
252 pop xBX
253 pop sAX
254 leave
255 ret
256
257.skip:
258 mov xAX, .s_szSse2Missing
259 call TMPL_NM_CMN(TestSubDone)
260 jmp .done
261
262.s_szSubTestName:
263 db TMPL_MODE_STR, ', cvtss2si et al.', 0
264.s_szSse2Missing:
265 db 'SSE2 is missing', 0
266ENDPROC TMPL_NM(TestCvtSize)
267
268
269;;
270; Test what CMPXCHG with 32-bit operand size does to 64-bit registers,
271; as this is not particularly well documented by either Intel or AMD.
272;
273; @uses No registers, but BS2_SEL_SPARE0 is trashed.
274;
275BEGINPROC TMPL_NM(TestCmpxchg32)
276 push xBP
277 mov xBP, xSP
278 push sAX
279 push xBX
280 push xCX
281 push xDX
282 push xDI
283 push xSI
284 sub xSP, 80h ; iret stack frame space.
285 mov xSI, xSP ; Save the stack register.
286
287 mov xAX, .s_szSubTestName
288 call TMPL_NM_CMN(TestSub)
289
290%ifdef TMPL_64BIT
291
292 ;
293 ; CMPXCHG reg, reg - values not equal, eax written
294 ;
295 mov rax, -1 ; Load registers with 64-bit values
296 mov rbx, -2
297 mov rcx, -3
298 cmpxchg ebx, ecx ; Not equal, writes eax
299 mov edx, -2 ; Clears high dword
300 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG reg, unequal, rax set"
301 mov rdx, -2 ; All ones still in high dword
302 TEST_ASSERT_SIMPLE rbx, rdx, jz, "CMPXCHG reg, unequal, rbx not set"
303
304 ;
305 ; CMPXCHG reg, reg - values equal, first operand written
306 ;
307 mov rax, -4 ; Load registers with 64-bit values
308 mov rbx, -4
309 mov rcx, -5
310 cmpxchg ebx, ecx ; Equal, writes ecx to ebx
311 mov edx, -5 ; Clears high dword
312 TEST_ASSERT_SIMPLE rbx, rdx, jz, "CMPXCHG reg, equal, rbx set"
313 mov rdx, -4 ; All ones still in high dword
314 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG reg, equal, rax not set"
315
316 ;
317 ; CMPXCHG mem, reg - values not equal, eax written
318 ;
319 mov rax, -1 ; Load registers with 64-bit values
320 mov rbx, -2
321 push rbx
322 mov rcx, -3
323 cmpxchg [rsp], ecx ; Not equal, writes eax
324 mov edx, -2 ; Clears high dword
325 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG mem, unequal, rax set"
326 pop rbx
327
328 ;
329 ; CMPXCHG mem, reg - values equal, first operand written
330 ;
331 mov rax, -4 ; Load registers with 64-bit values
332 mov rbx, -4
333 push rbx
334 mov rcx, -5
335 cmpxchg [rsp], ecx ; Not equal, writes eax
336 mov rdx, -4 ; All ones in high dword
337 TEST_ASSERT_SIMPLE rax, rdx, jz, "CMPXCHG mem, equal, rax not set"
338 pop rbx
339
340%endif
341
342 ;
343 ; Done.
344 ;
345 call TMPL_NM_CMN(TestSubDone)
346.done:
347 mov xSP, xSI
348 add xSP, 80h
349 pop xSI
350 pop xDI
351 pop xDX
352 pop xCX
353 pop xBX
354 pop sAX
355 leave
356 ret
357
358.s_szSubTestName:
359 db TMPL_MODE_STR, ', 32-bit CMPXCHG in 64-bit mode', 0
360ENDPROC TMPL_NM(TestCmpxchg32)
361
362
363;;
364; Proving intel manual wrong about using REX.X for BSWAP R8-R15 on 64-bit.
365; Checking the 'undefined' 16-bit bswap behavior.
366;
367; @uses No registers, but BS2_SEL_SPARE0 is trashed.
368;
369BEGINPROC TMPL_NM(TestBSwap)
370 push xBP
371 mov xBP, xSP
372 push sAX
373 push xBX
374 push xCX
375 push xDX
376 push xDI
377 push xSI
378 sub xSP, 80h ; iret stack frame space.
379 mov xSI, xSP ; Save the stack register.
380
381 mov xAX, .s_szSubTestName
382 call TMPL_NM_CMN(TestSub)
383
384 ;
385 ; Assert sanity.
386 ;
387 mov eax, 11223344h
388 bswap eax
389 TEST_ASSERT_SIMPLE eax, 44332211h, jz, "32-bit BSWAP EAX"
390
391 ;
392 ; Buggy manual (325383-041US, December 2011).
393 ;
394%ifdef TMPL_64BIT
395 push r8
396
397 mov r8d, 55667788h
398 mov eax, 55667788h
399 db X86_OP_REX_X
400 bswap eax ; does it access r8 or eax?
401 TEST_ASSERT_SIMPLE eax, 88776655h, jz, "REX.X BSWAP EAX - Wrong EAX."
402 TEST_ASSERT_SIMPLE r8, 55667788h, jz, "REX.X BSWAP EAX - Wrong R8."
403
404 mov r8d, 55667788h
405 mov eax, 55667788h
406 db X86_OP_REX_R
407 bswap eax ; does it access r8 or eax?
408 TEST_ASSERT_SIMPLE eax, 88776655h, jz, "REX.R BSWAP EAX - Wrong EAX."
409 TEST_ASSERT_SIMPLE r8, 55667788h, jz, "REX.R BSWAP EAX - Wrong R8."
410
411 mov r8d, 55667788h
412 mov eax, 55667788h
413 db X86_OP_REX_B
414 bswap eax ; does it access r8 or eax?
415 TEST_ASSERT_SIMPLE rax, 55667788h, jz, "REX.B BSWAP R8D - Wrong RAX."
416 TEST_ASSERT_SIMPLE r8d, 88776655h, jz, "REX.B BSWAP R8D - Wrong R8D."
417
418 pop r8
419%endif
420
421 ;
422 ; 'Undefined' 16-bit behavior.
423 ;
424 ; Zeroing of the lower 16-bits has been observed on:
425 ; - Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz
426 ;
427%ifndef TestBSwap16_defined
428 %define TestBSwap16_defined
429 %macro TestBSwap16 3,
430 mov %3, %2 ; save the primary register.
431 %ifdef TMPL_64BIT
432 mov %2, 0ffffffff98765432h ; Set the upper bit as well.
433 %else
434 mov %2, 98765432h
435 %endif
436 %ifndef TMPL_16BIT
437 db X86_OP_PRF_SIZE_OP
438 %endif
439 bswap %1
440 xchg %2, %3 ; Restore and save the result (xSP).
441 TEST_ASSERT_SIMPLE %3, 98760000h, jz, "Unexpected 16-bit BSWAP error."
442 %endmacro
443%endif
444
445 TestBSwap16 eax, sAX, sSI
446 TestBSwap16 ebx, sBX, sSI
447 TestBSwap16 ecx, sCX, sSI
448 TestBSwap16 edx, sDX, sSI
449 TestBSwap16 esp, sSP, sSI
450 TestBSwap16 ebp, sBP, sSI
451 TestBSwap16 edi, sDI, sSI
452 TestBSwap16 esi, sSI, sDI
453%ifdef TMPL_64BIT
454 TestBSwap16 r8d, r8, rax
455 TestBSwap16 r9d, r9, rax
456 TestBSwap16 r10d, r10, rax
457 TestBSwap16 r11d, r11, rax
458 TestBSwap16 r12d, r12, rax
459 TestBSwap16 r13d, r13, rax
460 TestBSwap16 r14d, r14, rax
461 TestBSwap16 r15d, r15, rax
462%endif
463
464 ;
465 ; Done.
466 ;
467 call TMPL_NM_CMN(TestSubDone)
468.done:
469 mov xSP, xSI
470 add xSP, 80h
471 pop xSI
472 pop xDI
473 pop xDX
474 pop xCX
475 pop xBX
476 pop sAX
477 leave
478 ret
479
480.s_szSubTestName:
481 db TMPL_MODE_STR, ', bswap', 0
482ENDPROC TMPL_NM(TestBSwap)
483
484
485;;
486; Do the tests for this mode.
487;
488; @uses nothing
489;
490BEGINCODELOW
491BITS 16
492BEGINPROC TMPL_NM(DoTestsForMode_rm)
493 push bp
494 mov bp, sp
495 push ax
496
497 ;
498 ; Check if the mode and NX is supported, do the switch.
499 ;
500 call TMPL_NM(Bs2IsModeSupported_rm)
501 jz .done
502 call TMPL_NM(Bs2EnterMode_rm)
503BITS TMPL_BITS
504
505 ;
506 ; Test exception handler basics using INT3 and #BP.
507 ;
508
509 call TMPL_NM(TestMemFences)
510 call TMPL_NM(TestBSwap)
511%ifdef TMPL_64BIT
512 ; Specifically tests 64-bit behavior.
513 call TMPL_NM(TestCvtSize)
514 call TMPL_NM(TestCmpxchg32)
515%endif
516
517 ;
518 ; Back to real mode.
519 ;
520 call TMPL_NM(Bs2ExitMode)
521BITS 16
522 call Bs2DisableNX_r86
523
524.done:
525 pop ax
526 leave
527 ret
528ENDPROC TMPL_NM(DoTestsForMode_rm)
529TMPL_BEGINCODE
530BITS TMPL_BITS
531
532%include "bootsector2-template-footer.mac"
533
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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