VirtualBox

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

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 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: 27.4 KB
Line 
1; $Id: bootsector2-cpu-pf-1-template.mac 106061 2024-09-16 14:03:52Z vboxsync $
2;; @file
3; Bootsector test for various types of #PFs - multi mode template.
4;
5
6;
7; Copyright (C) 2007-2024 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%undef BIG_PAGE_SIZE
45%undef PXE_SIZE
46%ifdef TMPL_CMN_PP
47 %define BIG_PAGE_SIZE _4M
48 %define PXE_SIZE 4
49%else
50 %define BIG_PAGE_SIZE _2M
51 %define PXE_SIZE 8
52%endif
53
54
55;;
56; Do the tests for this mode.
57;
58; @uses nothing
59;
60BEGINCODELOW
61BITS 16
62BEGINPROC TMPL_NM(DoTestsForMode_rm)
63 push bp
64 mov bp, sp
65 push ax
66
67 ;
68 ; Check if the mode and NX is supported, do the switch.
69 ;
70 call TMPL_NM(Bs2IsModeSupported_rm)
71 jz .done
72 mov ax, [bp - 2]
73 test al, al
74 jz .nx_disabled
75 call Bs2IsNXSupported_r86
76 jz .done
77 call Bs2EnableNX_r86
78.nx_disabled:
79 call TMPL_NM(Bs2EnterMode_rm)
80BITS TMPL_BITS
81
82 ;
83 ; Do the tests.
84 ;
85 call TMPL_NM(TestNotPresent)
86 ;; @todo call TMPL_NM(TestReadOnly)
87 ;; @todo call TMPL_NM(TestSupervisor)
88 ;; @todo call TMPL_NM(TestReservedBits)
89
90 ;
91 ; Back to real mode.
92 ;
93 call TMPL_NM(Bs2ExitMode)
94BITS 16
95 call Bs2DisableNX_r86
96
97.done:
98 pop ax
99 leave
100 ret
101ENDPROC TMPL_NM(DoTestsForMode_rm)
102TMPL_BEGINCODE
103BITS TMPL_BITS
104
105
106;;
107; Do the tests for this mode.
108;
109; @uses nothing
110;
111BEGINCODELOW
112BITS 16
113BEGINPROC TMPL_NM(DoBenchmarksForMode_rm)
114 push bp
115 mov bp, sp
116 push ax
117
118 ;
119 ; Check if the mode and NX is supported, do the switch.
120 ;
121 call TMPL_NM(Bs2IsModeSupported_rm)
122 jz .done
123 call TMPL_NM(Bs2EnterMode_rm)
124BITS TMPL_BITS
125
126 ;
127 ; Do the tests.
128 ;
129 call TMPL_NM(BenchmarkNotPresent)
130
131 ;
132 ; Back to real mode.
133 ;
134 call TMPL_NM(Bs2ExitMode)
135BITS 16
136.done:
137 pop ax
138 leave
139 ret
140ENDPROC TMPL_NM(DoBenchmarksForMode_rm)
141TMPL_BEGINCODE
142BITS TMPL_BITS
143
144
145;;
146; Does the page-not-present tests.
147;
148; @param al Set if NXE=1, clear if NXE=0.
149;
150; @uses nothing
151;
152BEGINPROC TMPL_NM(TestNotPresent)
153 push xBP
154 mov xBP, xSP
155 push sAX
156 push xBX
157 push xCX
158 push xDX
159 push xDI
160 push xSI
161
162 ;
163 ; Setup sCX for all the following tests.
164 ;
165 xor sCX, sCX
166 test al, al
167 jz .no_nxe
168 mov sCX, X86_TRAP_PF_ID
169.no_nxe:
170
171 ;
172 ; First test, big page not present.
173 ;
174 mov xAX, .s_szBigPageNotPresent
175 test sCX, sCX
176 jz .test1_nxe
177 mov xAX, .s_szBigPageNotPresentNX
178.test1_nxe:
179 call TMPL_NM_CMN(TestSub)
180 call TMPL_NM(TestFillTestAreaWithRet)
181
182 mov sAX, TST_SCRATCH_PD_BASE
183 call TMPL_NM(TestGetPdeAddr)
184 and byte [sAX], ~X86_PTE_P
185 mov sAX, cr3
186 mov cr3, sAX
187
188 mov sAX, TST_SCRATCH_PD_BASE
189 mov sDX, 0 ; err code
190 call TMPL_NM(TestHammerPage)
191 jz .test1_cleanup
192
193 mov sAX, TST_SCRATCH_PD_BASE + (BIG_PAGE_SIZE / 2 - _4K)
194 call TMPL_NM(TestHammerPage)
195 jz .test1_cleanup
196
197 mov sAX, TST_SCRATCH_PD_BASE + (BIG_PAGE_SIZE - _4K)
198 call TMPL_NM(TestHammerPage)
199 jz .test1_cleanup
200
201.test1_cleanup:
202 mov sAX, TST_SCRATCH_PD_BASE
203 call TMPL_NM(TestGetPdeAddr)
204 or byte [sAX], X86_PTE_P
205 mov sAX, cr3
206 mov cr3, sAX
207
208 ;
209 ; The second test, normal page not present.
210 ;
211 mov xAX, .s_szPageNotPresent
212 test sCX, sCX
213 jz .test2_nxe
214 mov xAX, .s_szPageNotPresentNX
215.test2_nxe:
216 call TMPL_NM_CMN(TestSub)
217
218 mov sAX, TST_SCRATCH_PD_BASE
219 call TMPL_NM(TstPutPageTableAt)
220
221 ; Make the first and last page not-present.
222 and byte [BS2_USER_PX_0_ADDR], ~X86_PTE_P
223 and byte [BS2_USER_PX_0_ADDR + 01000h - PXE_SIZE], ~X86_PTE_P
224 mov sAX, cr3
225 mov cr3, sAX
226
227 ; Do the tests.
228 mov sAX, TST_SCRATCH_PD_BASE
229 mov sDX, 0 ; err code
230 call TMPL_NM(TestHammerPage)
231 jz .test2_cleanup
232
233 mov sAX, TST_SCRATCH_PD_BASE + (BIG_PAGE_SIZE - _4K)
234 call TMPL_NM(TestHammerPage)
235 jz .test2_cleanup
236
237.test2_cleanup:
238 mov sAX, TST_SCRATCH_PD_BASE
239 call TMPL_NM(TstRestoreBigPageAt)
240
241
242%if PXE_SIZE == 8 ; PAE or LM
243 ;
244 ; The third test, mark a page directory pointer entry not present.
245 ;
246 mov xAX, .s_szPdpeNotPresent
247 test sCX, sCX
248 jz .test3_nxe
249 mov xAX, .s_szPdpeNotPresentNX
250.test3_nxe:
251 call TMPL_NM_CMN(TestSub)
252 call TMPL_NM(TestFillTestAreaWithRet)
253
254 mov sAX, TST_SCRATCH_PDPT_BASE
255 call TMPL_NM(TestGetPdpeAddr)
256 and byte [sAX], ~X86_PTE_P
257 mov sAX, cr3
258 mov cr3, sAX
259
260 mov sAX, TST_SCRATCH_PDPT_BASE
261 mov sDX, 0 ; err code
262 call TMPL_NM(TestHammerPage)
263 jz .test3_cleanup
264
265 mov sAX, TST_SCRATCH_PDPT_BASE + (BIG_PAGE_SIZE / 2 - _4K)
266 call TMPL_NM(TestHammerPage)
267 jz .test3_cleanup
268
269 mov sAX, TST_SCRATCH_PDPT_BASE + (BIG_PAGE_SIZE - _4K)
270 call TMPL_NM(TestHammerPage)
271 jz .test3_cleanup
272
273.test3_cleanup:
274 mov sAX, TST_SCRATCH_PDPT_BASE
275 call TMPL_NM(TestGetPdpeAddr)
276 or byte [sAX], X86_PTE_P
277 mov sAX, cr3
278 mov cr3, sAX
279%endif ; PAE || LM
280
281
282%ifdef TMPL_LM64
283 ;
284 ; The fourth test, mark a page map level 4 entry not present.
285 ;
286 mov xAX, .s_szPml4eNotPresent
287 test sCX, sCX
288 jz .test4_nxe
289 mov xAX, .s_szPml4eNotPresentNX
290.test4_nxe:
291 call TMPL_NM_CMN(TestSub)
292 call TMPL_NM(TestFillTestAreaWithRet)
293
294 mov sAX, TST_SCRATCH_PML4_BASE
295 call TMPL_NM(TestGetPml4eAddr)
296 and byte [sAX], ~X86_PTE_P
297 mov sAX, cr3
298 mov cr3, sAX
299
300 mov sAX, TST_SCRATCH_PML4_BASE
301 mov sDX, 0 ; err code
302 call TMPL_NM(TestHammerPage)
303 jz .test4_cleanup
304
305 mov sAX, TST_SCRATCH_PML4_BASE + (BIG_PAGE_SIZE / 2 - _4K)
306 call TMPL_NM(TestHammerPage)
307 jz .test4_cleanup
308
309 mov sAX, TST_SCRATCH_PML4_BASE + (BIG_PAGE_SIZE - _4K)
310 call TMPL_NM(TestHammerPage)
311 jz .test4_cleanup
312
313.test4_cleanup:
314 mov sAX, TST_SCRATCH_PML4_BASE
315 call TMPL_NM(TestGetPml4eAddr)
316 or byte [sAX], X86_PTE_P
317 mov sAX, cr3
318 mov cr3, sAX
319%endif
320
321 ;
322 ; Done.
323 ;
324 call TMPL_NM_CMN(TestSubDone)
325
326 pop xSI
327 pop xDI
328 pop xDX
329 pop xCX
330 pop xBX
331 pop sAX
332 leave
333 ret
334
335.s_szBigPageNotPresent:
336 db TMPL_MODE_STR, ', !NX, big page NP', 0
337.s_szBigPageNotPresentNX:
338 db TMPL_MODE_STR, ', NX, big page NP', 0
339.s_szPageNotPresent:
340 db TMPL_MODE_STR, ', !NX, page NP', 0
341.s_szPageNotPresentNX:
342 db TMPL_MODE_STR, ', NX, page NP', 0
343%if PXE_SIZE == 8 ; PAE or LM
344.s_szPdpeNotPresent:
345 db TMPL_MODE_STR, ', !NX, PDPE NP', 0
346.s_szPdpeNotPresentNX:
347 db TMPL_MODE_STR, ', NX, PDPE NP', 0
348%endif
349%ifdef TMPL_LM64
350.s_szPml4eNotPresent:
351 db TMPL_MODE_STR, ', !NX, PML4E NP', 0
352.s_szPml4eNotPresentNX:
353 db TMPL_MODE_STR, ', NX, PML4E NP', 0
354%endif
355ENDPROC TMPL_NM(TestNotPresent)
356
357
358
359;;
360; Does the page-not-present benchmark.
361;
362; @uses nothing
363;
364BEGINPROC TMPL_NM(BenchmarkNotPresent)
365 push xBP
366 mov xBP, xSP
367 push sAX
368 push xBX
369 push sCX
370 push sDX
371 push xDI
372 push xSI
373 sub xSP, 20h
374
375 call TMPL_NM(TestFillTestAreaWithRet)
376
377 ;
378 ; The First benchmark: Big page not present.
379 ;
380
381 ; Mark the big test page not present.
382 mov sAX, TST_SCRATCH_PD_BASE
383 call TMPL_NM(TestGetPdeAddr)
384 and byte [sAX], ~X86_PTE_P
385 mov sAX, cr3
386 mov cr3, sAX
387
388 ; Benchmark.
389 mov sAX, TST_SCRATCH_PD_BASE
390 mov xDX, .s_szBigPageNotPresent
391 mov xCX, .s_szBigPageNotPresentFailed
392 call TMPL_NM(TstBenchmark32BitReads)
393
394 ; Cleanup.
395 mov sAX, TST_SCRATCH_PD_BASE
396 call TMPL_NM(TestGetPdeAddr)
397 or byte [sAX], X86_PTE_P
398 mov sAX, cr3
399 mov cr3, sAX
400
401 ;
402 ; The second benchmark: Normal page not present.
403 ;
404
405 ; Replace the big page with a page table and make the first and last
406 ; pages not-present.
407 mov sAX, TST_SCRATCH_PD_BASE
408 call TMPL_NM(TstPutPageTableAt)
409
410 and byte [BS2_USER_PX_0_ADDR], ~X86_PTE_P
411 and byte [BS2_USER_PX_0_ADDR + 01000h - PXE_SIZE], ~X86_PTE_P
412 mov sAX, cr3
413 mov cr3, sAX
414
415 ; Benchmark.
416 mov sAX, TST_SCRATCH_PD_BASE
417 mov xDX, .s_szPageNotPresent
418 mov xCX, .s_szPageNotPresentFailed
419 call TMPL_NM(TstBenchmark32BitReads)
420
421 ; Cleanup
422 mov sAX, TST_SCRATCH_PD_BASE
423 call TMPL_NM(TstRestoreBigPageAt)
424
425
426 ;
427 ; Done.
428 ;
429 add xSP, 20h
430 pop xSI
431 pop xDI
432 pop sDX
433 pop sCX
434 pop xBX
435 pop sAX
436 leave
437 ret
438
439.s_szBigPageNotPresent:
440 db TMPL_MODE_STR, ', read NP big page', 0
441.s_szBigPageNotPresentFailed:
442 db TMPL_MODE_STR, ', reading NP big page failed', 13, 10, 0
443.s_szPageNotPresent:
444 db TMPL_MODE_STR, ', read NP page', 0
445.s_szPageNotPresentFailed:
446 db TMPL_MODE_STR, ', reading NP page failed', 13, 10, 0
447ENDPROC TMPL_NM(BenchmarkNotPresent)
448
449
450;;
451; Benchmark 32-bit reads at a give location.
452;
453; Will report the result under the name given via xDX. Will report any test
454; failure giving the string pointed to by xCX as explanation.
455;
456; @param sAX The location to do the reads.
457; @param xDX The test value name.
458; @param xCX The failure string
459; @uses nothing
460;
461BEGINPROC TMPL_NM(TstBenchmark32BitReads)
462 push xBP
463 mov xBP, xSP
464%define a_pu32Test [xBP - sCB]
465 push sAX
466%define a_pszValue [xBP - sCB*2]
467 push sDX
468%define a_pszFailure [xBP - sCB*3]
469 push sCX
470 push sSI
471 push sDI
472%define u64NanoTS [xBP - sCB*5 - 8h]
473 sub xSP, 8h
474
475 ;
476 ; Calibrate the test so it doesn't take forever.
477 ;
478 mov xAX, .calibrate_resume
479 mov dl, 0eh
480 call TMPL_NM_CMN(Bs2TrapPrepare)
481 mov ecx, TST_CALIBRATE_LOOP_COUNT
482
483 lea xAX, u64NanoTS
484 call TMPL_NM_CMN(GetNanoTS)
485
486.calibrate_loop:
487 mov sAX, a_pu32Test
488 mov esi, [sAX]
489.calibrate_resume:
490 test sAX, sAX
491 jnz .failure
492 dec ecx
493 jnz .calibrate_loop
494
495 lea xAX, u64NanoTS
496 call TMPL_NM_CMN(GetElapsedNanoTS)
497 call TMPL_NM_CMN(Bs2TrapReset)
498
499 ; Figure out how many iterations is required for the full benchmark.
500 mov ecx, TST_BENCHMARK_PERIOD_IN_SECS
501 mov edx, TST_CALIBRATE_LOOP_COUNT
502 mov xAX, xSP
503 call TMPL_NM_CMN(CalcBenchmarkIterations)
504 mov ecx, eax ; iteration count.
505
506 ;
507 ; Do the full benchmark run.
508 ;
509 mov xAX, .bench_resume
510 mov dl, 0eh
511 call TMPL_NM_CMN(Bs2TrapPrepare)
512 mov edx, ecx ; save test count for ReportResult.
513
514 lea xAX, u64NanoTS
515 call TMPL_NM_CMN(GetNanoTS)
516.bench_loop:
517 mov xAX, a_pu32Test
518 mov esi, [eax]
519.bench_resume:
520 test eax, eax
521 jnz .failure
522 dec ecx
523 jnz .bench_loop
524
525 lea xAX, u64NanoTS
526 call TMPL_NM_CMN(GetElapsedNanoTS)
527 call TMPL_NM_CMN(Bs2TrapReset)
528
529 mov xCX, a_pszValue
530 lea xAX, u64NanoTS
531 call TMPL_NM_CMN(ReportResult)
532
533.return:
534 pop sDI
535 pop sSI
536 pop sCX
537 pop sDX
538 pop sAX
539 leave
540 ret
541
542.failure:
543 call TMPL_NM_CMN(Bs2TrapReset)
544 mov xAX, a_pszFailure
545 call TMPL_NM_CMN(TestFailed)
546 jmp .return
547
548%undef a_pszFailure
549%undef a_pu32Test
550%undef a_pszValue
551%undef a_pszFailure
552%undef u64NanoTS
553ENDPROC TMPL_NM(TstBenchmark32BitReads)
554
555
556;;
557; Fills the test area with return instructions.
558;
559; @uses nothing.
560;
561BEGINPROC TMPL_NM(TestFillTestAreaWithRet)
562 push xBP
563 mov xBP, xSP
564 push xDI
565 push xCX
566 push xAX
567
568 mov xDI, TST_SCRATCH_PD_BASE
569 mov xCX, (_4M + _4M) / 4
570 mov eax, 0c3c3c3c3h
571 rep stosd
572
573 mov xDI, TST_SCRATCH_PDPT_BASE
574 mov xCX, (_4M + _4M) / 4
575 mov eax, 0c3c3c3c3h
576 rep stosd
577
578%ifdef TMPL_LM64
579 mov xDI, TST_SCRATCH_PML4_BASE
580 mov xCX, (_4M + _4M) / 8
581 mov rax, 0c3c3c3c3c3c3c3c3h
582 rep stosq
583%endif
584
585 pop xAX
586 pop xCX
587 pop xDI
588 leave
589 ret
590ENDPROC TMPL_NM(TestFillTestAreaWithRet)
591
592
593;;
594; Gets the page directory address.
595;
596; ASSUMES identity mapped page translation tables.
597;
598; @returns ds:xAX The page directory address.
599; @param sAX The virtual address in question.
600; @uses nothing
601;
602BEGINPROC TMPL_NM(TestGetPdeAddr)
603 push xBP
604 mov xBP, xSP
605 push sBX
606 push sCX
607
608%ifdef TMPL_CMN_PP
609 ; PDPE
610 shr sAX, X86_PD_SHIFT
611 and sAX, X86_PD_MASK
612 shl sAX, 2
613 mov sBX, cr3
614 and sBX, X86_CR3_PAGE_MASK
615 add sAX, sBX
616
617%else
618 %ifdef TMPL_CMN_LM
619 ; PML4E
620 mov sCX, sAX
621 shr sCX, X86_PML4_SHIFT
622 and sCX, X86_PML4_MASK
623 shl sCX, 3
624 mov sBX, cr3
625 and sBX, X86_CR3_AMD64_PAGE_MASK & 0ffffffffh
626 add sBX, sCX
627 mov sBX, [sBX]
628 and sBX, X86_PDPE_PG_MASK & 0ffffffffh
629 %else
630 mov sBX, cr3
631 and sBX, X86_CR3_PAE_PAGE_MASK
632 %endif
633
634 ; PDPE
635 mov sCX, sAX
636 shr sCX, X86_PDPT_SHIFT
637 %ifdef TMPL_CMN_LM
638 and sCX, X86_PDPT_MASK_AMD64
639 %else
640 and sCX, X86_PDPT_MASK_PAE
641 %endif
642 shl sCX, 3
643 add sBX, xCX
644 mov sBX, [sBX]
645 and sBX, X86_PDPE_PG_MASK & 0ffffffffh
646
647 ; PDE
648 shr sAX, X86_PD_PAE_SHIFT
649 and sAX, X86_PD_PAE_MASK
650 shl sAX, 3
651 add sAX, sBX
652%endif
653
654 pop sCX
655 pop sBX
656 leave
657 ret
658ENDPROC TMPL_NM(TestGetPdeAddr)
659
660
661%if PXE_SIZE == 8 ; PAE or LM
662;;
663; Gets the page directory pointer entry for an address.
664;
665; ASSUMES identity mapped page translation tables.
666;
667; @returns ds:xAX The pointer to the PDPE.
668; @param sAX The virtual address in question.
669; @uses nothing
670;
671BEGINPROC TMPL_NM(TestGetPdpeAddr)
672 push xBP
673 mov xBP, xSP
674 push sBX
675 push sCX
676
677%ifdef TMPL_CMN_PP
678 %error "misconfig"
679%endif
680
681%ifdef TMPL_CMN_LM
682 ; PML4E
683 mov sCX, sAX
684 shr sCX, X86_PML4_SHIFT
685 and sCX, X86_PML4_MASK
686 shl sCX, 3
687 mov sBX, cr3
688 and sBX, X86_CR3_AMD64_PAGE_MASK & 0ffffffffh
689 add sBX, sCX
690 mov sBX, [sBX]
691 and sBX, X86_PDPE_PG_MASK & 0ffffffffh
692%else
693 mov sBX, cr3
694 and sBX, X86_CR3_PAE_PAGE_MASK
695%endif
696
697 ; PDPE
698 shr sAX, X86_PDPT_SHIFT
699%ifdef TMPL_CMN_LM
700 and sAX, X86_PDPT_MASK_AMD64
701%else
702 and sAX, X86_PDPT_MASK_PAE
703%endif
704 shl sAX, 3
705 add sAX, sBX
706
707 pop sCX
708 pop sBX
709 leave
710 ret
711ENDPROC TMPL_NM(TestGetPdpeAddr)
712%endif ; PAE or LM
713
714
715%ifdef TMPL_CMN_LM
716;;
717; Gets the page map level 4 entry for an address.
718;
719; ASSUMES identity mapped page translation tables.
720;
721; @returns rax The pointer to the PML4E.
722; @param rax The virtual address in question.
723; @uses nothing
724;
725BEGINPROC TMPL_NM(TestGetPml4eAddr)
726 push xBP
727 mov xBP, xSP
728 push rbx
729
730 ; PML4E
731 shr rax, X86_PML4_SHIFT
732 and rax, X86_PML4_MASK
733 shl rax, 3
734 mov rbx, cr3
735 and rbx, X86_CR3_AMD64_PAGE_MASK & 0ffffffffh
736 add rax, rbx
737
738 pop rbx
739 leave
740 ret
741ENDPROC TMPL_NM(TestGetPml4eAddr)
742%endif ; TMPL_CMN_LM
743
744
745;;
746; Initialize page table #0 and hooks it up at the specified address.
747;
748; The page table will have identity mapped pages. The TLBs are flushed
749; wholesale. The caller will have to reconstruct the PDE when finished.
750;
751; @param sAX The virtual address (big page -> page table).
752; @uses nothing
753;
754BEGINPROC TMPL_NM(TstPutPageTableAt)
755 push xBP
756 mov xBP, xSP
757 push sAX
758 push sCX
759 push sDI
760 push sSI
761
762 ; initialize a page table.
763 mov sDI, BS2_USER_PX_0_ADDR
764 mov sSI, sAX
765.init_loop:
766%if PXE_SIZE == 8
767 mov [sDI + 4], dword 0
768 mov [sDI], sSI
769%else
770 mov [sDI], esi
771%endif
772 or byte [sDI], X86_PTE_P | X86_PTE_RW
773 add sSI, _4K
774 add sDI, PXE_SIZE
775 test sDI, 0fffh
776 jnz .init_loop
777
778 ; hook it up instead of the big page.
779 and sAX, ~(BIG_PAGE_SIZE - 1)
780 mov sDI, sAX
781 call TMPL_NM(TestGetPdeAddr)
782 mov dword [sAX], BS2_USER_PX_0_ADDR | X86_PDE_P | X86_PDE_RW | X86_PDE_RW
783%if PXE_SIZE == 8
784 mov dword [sAX + 4], 0
785%endif
786 mov sAX, cr3
787 mov cr3, sAX
788
789 ; Make sure it works.
790 mov eax, 0c3c3c3c3h
791 mov ecx, BIG_PAGE_SIZE / 4
792 rep stosd
793
794 pop sSI
795 pop sDI
796 pop sCX
797 pop sAX
798 leave
799 ret
800ENDPROC TMPL_NM(TstPutPageTableAt)
801
802
803;;
804; Restores the big page for a virtual address, undoing harm done by a
805; previous TstPutPageTableAt call.
806;
807; @param sAX The virtual address to restore to a big page.
808; @uses nothing
809;
810BEGINPROC TMPL_NM(TstRestoreBigPageAt)
811 push xBP
812 mov xBP, xSP
813 push sAX
814 push sCX
815 push sDI
816
817 ; Set it up, inheriting bits from the previous PDE.
818 and sAX, ~(BIG_PAGE_SIZE - 1)
819 mov sDI, sAX ; save it for later.
820 call TMPL_NM(TestGetPdeAddr)
821 mov sCX, [sAX - PXE_SIZE]
822 and sCX, X86_PDE4M_US | X86_PDE4M_RW | X86_PDE4M_G | X86_PDE4M_PAT | X86_PDE4M_AVL | X86_PDE4M_PCD | X86_PDE4M_PWT
823 or sCX, X86_PDE4M_P | X86_PDE4M_PS
824 or sCX, sDI
825%if PXE_SIZE == 8
826 mov dword [sAX + 4], 0
827 mov [sAX], sCX
828%else
829 mov [sAX], ecx
830%endif
831 mov sAX, cr3
832 mov cr3, sAX
833
834 ; Make sure it works.
835 mov eax, 0c3c3c3c3h
836 mov ecx, BIG_PAGE_SIZE / 4
837 rep stosd
838
839 pop sDI
840 pop sCX
841 pop sAX
842 leave
843 ret
844ENDPROC TMPL_NM(TstRestoreBigPageAt)
845
846
847
848;;
849; Hammers a page.
850;
851; Accesses a page in a few different ways, expecting all of the accesses to
852; cause some kind of page fault. The caller just makes sure the page causes
853; a fault and points us to it.
854;
855; @returns al=1, ZF=0 on success.
856; @returns al=0, ZF=1 on failure.
857; @param sAX The page.
858; @param sDX The base error code to expect.
859; @param xCX X86_TRAP_PF_ID if NXE, otherwise 0.
860; @uses al
861;
862BEGINPROC TMPL_NM(TestHammerPage)
863 push xBP
864 mov xBP, xSP
865 push sBX
866%define a_uErrorExec sPRE [xBP - sCB*2]
867 push sCX
868%define a_uErrorFixed sPRE [xBP - sCB*3]
869 push sDX
870 push sDI
871 push sSI
872%define a_pPage sPRE [xBP - sCB*6]
873 push sAX
874
875 ;
876 ; First reads of different sizes.
877 ;
878 mov sDI, a_pPage
879.read_byte_loop:
880 mov dl, 0ffh
881 mov xAX, .read_byte_resume
882 call TMPL_NM_CMN(Bs2TrapPrepare)
883.read_byte:
884 mov cl, byte [sDI]
885.read_byte_resume:
886 mov eax, 0eh ; trap #
887 mov sDX, a_uErrorFixed ; err
888 mov sCX, .read_byte ; fault eip
889 mov sBX, sDI ; fault address.
890 call TMPL_NM_CMN(TestCheckTrap)
891 jz .failed
892 inc sDI
893 test sDI, 0fffh
894 jnz .read_byte_loop
895
896 mov sDI, a_pPage
897.read_word_loop:
898 mov dl, 0ffh
899 mov xAX, .read_word_resume
900 call TMPL_NM_CMN(Bs2TrapPrepare)
901.read_word:
902 mov cx, word [sDI]
903.read_word_resume:
904 mov eax, 0eh ; trap #
905 mov sDX, a_uErrorFixed ; err
906 mov sCX, .read_word ; fault eip
907 mov sBX, sDI ; fault address.
908 call TMPL_NM_CMN(TestCheckTrap)
909 jz .failed
910 inc sDI
911 test sDI, 0fffh
912 jnz .read_word_loop
913
914 mov sDI, a_pPage
915.read_dword_loop:
916 mov dl, 0ffh
917 mov xAX, .read_dword_resume
918 call TMPL_NM_CMN(Bs2TrapPrepare)
919.read_dword:
920 mov ecx, dword [sDI]
921.read_dword_resume:
922 mov eax, 0eh ; trap #
923 mov sDX, a_uErrorFixed ; err
924 mov sCX, .read_dword ; fault eip
925 mov sBX, sDI ; fault address.
926 call TMPL_NM_CMN(TestCheckTrap)
927 jz .failed
928 inc sDI
929 test sDI, 0fffh
930 jnz .read_dword_loop
931
932 ;
933 ; Then writes of different sizes.
934 ;
935 mov sDI, a_pPage
936.write_byte_loop:
937 mov dl, 0ffh
938 mov xAX, .write_byte_resume
939 call TMPL_NM_CMN(Bs2TrapPrepare)
940.write_byte:
941 mov byte [sDI], 0c3h ; (ret instruction)
942.write_byte_resume:
943 mov eax, 0eh ; trap #
944 mov sDX, a_uErrorFixed ; err
945 or sDX, X86_TRAP_PF_RW
946 mov sCX, .write_byte ; fault eip
947 mov sBX, sDI ; fault address.
948 call TMPL_NM_CMN(TestCheckTrap)
949 jz .failed
950 inc sDI
951 test sDI, 0fffh
952 jnz .write_byte_loop
953
954 mov sDI, a_pPage
955.write_word_loop:
956 mov dl, 0ffh
957 mov xAX, .write_word_resume
958 call TMPL_NM_CMN(Bs2TrapPrepare)
959.write_word:
960 mov word [sDI], 0c3c3h ; (2 ret instructions)
961.write_word_resume:
962 mov eax, 0eh ; trap #
963 mov sDX, a_uErrorFixed ; err
964 or sDX, X86_TRAP_PF_RW
965 mov sCX, .write_word ; fault eip
966 mov sBX, sDI ; fault address.
967 call TMPL_NM_CMN(TestCheckTrap)
968 jz .failed
969 inc sDI
970 test sDI, 0fffh
971 jnz .write_word_loop
972
973 mov sDI, a_pPage
974.write_dword_loop:
975 mov dl, 0ffh
976 mov xAX, .write_dword_resume
977 call TMPL_NM_CMN(Bs2TrapPrepare)
978.write_dword:
979 mov dword [sDI], 0c3c3c3c3h ; (4 ret instructions)
980.write_dword_resume:
981 mov eax, 0eh ; trap #
982 mov sDX, a_uErrorFixed ; err
983 or sDX, X86_TRAP_PF_RW
984 mov sCX, .write_dword ; fault eip
985 mov sBX, sDI ; fault address.
986 call TMPL_NM_CMN(TestCheckTrap)
987 jz .failed
988 inc sDI
989 test sDI, 0fffh
990 jnz .write_dword_loop
991
992 ;
993 ; Execute access.
994 ;
995 mov sDI, a_pPage
996 mov xSI, xSP
997.call_loop:
998 mov dl, 0ffh
999 mov xAX, .call_resume
1000 call TMPL_NM_CMN(Bs2TrapPrepare)
1001 call sDI
1002.call_resume:
1003 mov xSP, xSI ; restore xSP since the call will change it before #PF'ing.
1004 mov eax, 0eh ; trap #
1005 mov sDX, a_uErrorFixed ; err
1006 or sDX, a_uErrorExec
1007 mov sCX, sDI ; fault eip
1008 mov sBX, sDI ; fault address.
1009 call TMPL_NM_CMN(TestCheckTrap)
1010 jz .failed
1011 inc sDI
1012 test sDI, 0fffh
1013 jnz .call_loop
1014
1015
1016 mov sDI, a_pPage
1017 mov xSI, xSP
1018.jmp_loop:
1019 mov dl, 0ffh
1020 mov xAX, .jmp_resume
1021 call TMPL_NM_CMN(Bs2TrapPrepare)
1022 push .jmp_resume ; push a return address in case of failure.
1023 jmp sDI
1024.jmp_resume:
1025 mov xSP, xSI ; restore xSP in case the jmp didn't trap.
1026 mov eax, 0eh ; trap #
1027 mov sDX, a_uErrorFixed ; err
1028 or sDX, a_uErrorExec
1029 mov sCX, sDI ; fault eip
1030 mov sBX, sDI ; fault address.
1031 call TMPL_NM_CMN(TestCheckTrap)
1032 jz .failed
1033 inc sDI
1034 test sDI, 0fffh
1035 jnz .jmp_loop
1036
1037 ; successfull return.
1038 pop sAX
1039 xor al, al
1040 inc al
1041.return:
1042 pop sSI
1043 pop sDI
1044 pop sDX
1045 pop sCX
1046 pop sBX
1047 leave
1048 ret
1049
1050.failed:
1051 pop sAX
1052 xor al, al
1053 jmp .return
1054%undef a_uErrorFixed
1055%undef a_uErrorExec
1056%undef a_pPage
1057ENDPROC TMPL_NM(TestHammerPage)
1058
1059
1060%include "bootsector2-template-footer.mac"
1061
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