diff options
Diffstat (limited to '')
-rw-r--r-- | src/VBox/ValidationKit/bootsectors/bootsector2-cpu-a20-1-template.mac | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/bootsectors/bootsector2-cpu-a20-1-template.mac b/src/VBox/ValidationKit/bootsectors/bootsector2-cpu-a20-1-template.mac new file mode 100644 index 00000000..2b67f908 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bootsector2-cpu-a20-1-template.mac @@ -0,0 +1,385 @@ +; $Id: bootsector2-cpu-a20-1-template.mac $ +;; @file +; bootsector2 A20 - multi mode template. +; + +; +; Copyright (C) 2007-2023 Oracle and/or its affiliates. +; +; This file is part of VirtualBox base platform packages, as +; available from https://www.virtualbox.org. +; +; This program is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation, in version 3 of the +; License. +; +; This program is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program; if not, see <https://www.gnu.org/licenses>. +; +; The contents of this file may alternatively be used under the terms +; of the Common Development and Distribution License Version 1.0 +; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +; in the VirtualBox distribution, in which case the provisions of the +; CDDL are applicable instead of those of the GPL. +; +; You may elect to license modified versions of this file under the +; terms and conditions of either the GPL or the CDDL or both. +; +; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +; + + +%include "bootsector2-template-header.mac" + + +;; +; Inner loop dealing with one 64KB segment. +; +BEGINPROC TMPL_NM(TestA20_EnabledInner) +.inner_loop: + mov ah, [es:xDI] + mov al, [ds:xSI] + cmp al, ah + jne .inner_next + + not al + mov [es:xDI], al + cmp al, [ds:xSI] + mov [es:xDI], ah + je .failed + +.inner_next: + inc xDI + inc xSI + dec ecx + jnz .inner_loop + + clc + ret + +.failed: + push sBX + push sAX + push sSI + push sDI +%ifdef TMPL_16BIT + push cs +%endif + push .s_szModifiyError + call TMPL_NM_CMN(TestFailedF) + add xSP, sCB * 5 + stc + ret +.s_szModifiyError: + db TMPL_MODE_STR, '- Same memory; EDI=%RX32 ESI=%RX32 EAX=%RX32 EBX=%RX32', 13, 10, 0 +ENDPROC TMPL_NM(TestA20_EnabledInner) + + +;; +; Inner loop dealing with one 64KB segment. +; +BEGINPROC TMPL_NM(TestA20_DisabledInner) +.inner_loop: + mov ah, [es:xDI] + mov al, [ds:xSI] + cmp al, ah + jne .failed1 + + not al + mov [es:xDI], al + cmp al, [ds:xSI] + mov [es:xDI], ah + jne .failed2 + + inc xDI + inc xSI + dec ecx + jnz .inner_loop + + clc + ret + +.failed1: + push sCX + push sBX + push sAX + push sSI + push sDI +%ifdef TMPL_16BIT + push cs +%endif + push .s_szNotEqual + call TMPL_NM_CMN(TestFailedF) + add xSP, sCB * 6 + stc + ret +.s_szNotEqual: + db TMPL_MODE_STR, ' - Not equal; EDI=%RX32 ESI=%RX32 EAX=%RX32 EBX=%RX32 ECX=%RX32', 13, 10, 0 + +.failed2: + push sCX + push sBX + push sAX + push sSI + push sDI +%ifdef TMPL_16BIT + push cs +%endif + push .s_szModifiyError + call TMPL_NM_CMN(TestFailedF) + add xSP, sCB * 6 + stc + ret + +.s_szModifiyError: + db TMPL_MODE_STR, ' - Modify error; EDI=%RX32 ESI=%RX32 EAX=%RX32 EBX=%RX32 ECX=%RX32', 13, 10, 0 +ENDPROC TMPL_NM(TestA20_DisabledInner) + + +;; +; Scans memory calling sDX for each segment. +; +BEGINPROC TMPL_NM(TestA20_ScanMemory) + push sAX + push sBX + push sCX + push sDX + push sSI + push sDI + pushf + cli +%ifdef TMPL_16BIT + push es + push ds +%endif + + ; + ; The outer loop walks a segment (64 KB) at a time. + ; + mov ebx, _1M +.outer_loop: + + ; Set up the registers. +%ifdef TMPL_CMN_R86 + mov ax, 0ffffh + mov edi, 00010h + mov es, ax + mov ax, 00000h + mov esi, 00000h + mov ds, ax + mov ecx, 01000h ; at 101000 there was a VMMDevTesting MMIO page. +%elifdef TMPL_16BIT + ;; @todo need a selector we can modify. + jmp .done + +%else + mov edi, ebx + mov esi, ebx + and esi, ~_1M + mov ecx, _64K +%endif +%ifndef TMPL_CMN_R86 + ; Should we skip this segment or only check parts of it? + cmp esi, edi ; affected by A20? + je .outer_next + +%if BS2_PXX_LAST != 09ffffh + %error BS2_PXX_LAST does not have the expected value. +%endif + cmp ebx, BS2_PXX_BASE + _1M ; don't mess with page tables, stacks, MMIO or ROMs. + jb .not_low_rom_mmio_region + cmp ebx, _1M + _1M + jb .outer_next +.not_low_rom_mmio_region: + + cmp ebx, BS2_ADDR + _1M + ja .not_bs2 + mov ecx, BS2_ADDR ; don't overwrite our own code. +.not_bs2: + cmp ebx, _1M + jne .not_VMMDevTestingMMIO + mov ecx, 1000h ; don't bother with the MMIO +.not_VMMDevTestingMMIO: +%endif ; TMPL_CMN_R86 + + ; Invoke the callback. + call xDX + jc .failure + +%ifndef TMPL_CMN_R86 +.outer_next: + add ebx, _64K + cmp ebx, 32*_1M + jbe .outer_loop +%endif + +.done: +%ifdef TMPL_16BIT + pop ds + pop es +%endif + popf + pop sDI + pop sSI + pop sDX + pop sCX + pop sBX + pop sAX + ret + +.failure: +%if 1 + cmp ebx, _1M + je .contine_at_next_MB + cmp ebx, _2M + je .contine_at_next_MB + cmp ebx, _1M + _2M + je .contine_at_next_MB + cmp ebx, _4M + je .contine_at_next_MB +%endif + jmp .done + +.contine_at_next_MB: + add ebx, _1M + jmp .outer_loop +ENDPROC TMPL_NM(TestA20_ScanMemory) + + +BEGINPROC TMPL_NM(TestA20_Enabled) + push sDX + mov xDX, TMPL_NM(TestA20_EnabledInner) + call TMPL_NM(TestA20_ScanMemory) + pop sDX + ret +ENDPROC TMPL_NM(TestA20_Enabled) + + +;; +; Checks that the first 64KB at 1MB wraps is the same physical memory as at +; address 0. +; +BEGINPROC TMPL_NM(TestA20_Disabled) + push sDX + mov xDX, TMPL_NM(TestA20_DisabledInner) + call TMPL_NM(TestA20_ScanMemory) + pop sDX + ret +ENDPROC TMPL_NM(TestA20_Disabled) + + +BEGINPROC TMPL_NM(TestA20_FlushAll) + push sAX + wbinvd + mov sAX, cr3 + mov cr3, sAX + wbinvd + pop sAX + ret +ENDPROC TMPL_NM(TestA20_FlushAll) + + + +;; +; Do the A20 tests for this mode. +; +; @uses nothing +; +BEGINCODELOW +BITS 16 +BEGINPROC TMPL_NM(TestA20_rm) + push eax + + mov ax, .s_szTestName + call TestSub_r86 + + call TMPL_NM(Bs2IsModeSupported_rm) + jz .skip_not_supported + + ; + ; Do tests with A20 enabled. + ; + call Bs2EnableA20_r86 + call TMPL_NM(Bs2EnterMode_rm) +BITS TMPL_BITS + call TMPL_NM(TestA20_FlushAll) + call TMPL_NM(TestA20_Enabled) + call TMPL_NM(Bs2ExitMode) +BITS 16 + call TestSubErrorCount_r86 + cmp ax, 0 + jne .done + + ; + ; Do tests with A20 disabled. + ; + call Bs2DisableA20_r86 + call TMPL_NM(Bs2EnterMode_rm) +BITS TMPL_BITS + call TMPL_NM(TestA20_FlushAll) + call TMPL_NM(TestA20_Disabled) + call TMPL_NM(Bs2ExitMode) +BITS 16 + call TestSubErrorCount_r86 + cmp ax, 0 + jne .done + +%ifndef TMPL_CMN_V86 + ; + ; Change A20 state without leaving and entering the CPU mode. + ; + call Bs2EnableA20_r86 + call TMPL_NM(Bs2EnterMode_rm) +BITS TMPL_BITS + call TMPL_NM(TestA20_Enabled) + + call TMPL_NM_CMN(Bs2DisableA20) + call TMPL_NM(TestA20_FlushAll) + call TMPL_NM(TestA20_Disabled) + + call TMPL_NM_CMN(Bs2EnableA20) + call TMPL_NM(TestA20_FlushAll) + call TMPL_NM(TestA20_Enabled) + + call TMPL_NM_CMN(Bs2DisableA20) + call TMPL_NM(TestA20_FlushAll) + call TMPL_NM(TestA20_Disabled) + + call TMPL_NM_CMN(Bs2EnableA20) + call TMPL_NM(TestA20_FlushAll) + call TMPL_NM(TestA20_Enabled) + + call TMPL_NM(Bs2ExitMode) +BITS 16 +%endif ; !TMPL_CMN_V86 + +.done: + call Bs2DisableA20_r86 +.done1: + call TestSubDone_r86 + + pop eax + ret + +.skip_not_supported: + mov eax, .s_szSkipNotSupported + call TestSkipped_r86 + jmp .done1 + +.s_szTestName: + db TMPL_MODE_STR, 0 +.s_szSkipNotSupported: + db TMPL_MODE_STR, ' is not supported by the CPU', 10, 13, 0 +ENDPROC TMPL_NM(TestA20_rm) +TMPL_BEGINCODE +BITS TMPL_BITS + + +%include "bootsector2-template-footer.mac" + |