summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/bootsectors/bs3-cpu-state64-1-asm.asm
blob: 49d95f3f5552f33d9880295aa6666d58eec3c319 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
; $Id: bs3-cpu-state64-1-asm.asm $
;; @file
; BS3Kit - bs3-cpu-state64-1
;

;
; 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
;


;*********************************************************************************************************************************
;*  Header Files                                                                                                                 *
;*********************************************************************************************************************************
%include "bs3kit.mac"


;*********************************************************************************************************************************
;*  Global Variables                                                                                                             *
;*********************************************************************************************************************************
BS3_BEGIN_DATA16
BS3_GLOBAL_DATA g_bs3CpuState64CtxCaller, BS3REGCTX_size
        resb    BS3REGCTX_size
BS3_GLOBAL_DATA g_bs3CpuState64CtxToLoad, BS3REGCTX_size
        resb    BS3REGCTX_size
BS3_GLOBAL_DATA g_bs3CpuState64CtxSaved, BS3REGCTX_size
        resb    BS3REGCTX_size

BS3_GLOBAL_DATA g_bs3CpuState64RCX, 8
        dq      1


;*********************************************************************************************************************************
;*  External Symbols                                                                                                             *
;*********************************************************************************************************************************
BS3_BEGIN_TEXT64
EXTERN Bs3RegCtxRestore_c64
EXTERN Bs3RegCtxSave_c64


BS3_BEGIN_TEXT64
        BS3_SET_BITS 64

;;
;; Test worker that switches between 64-bit and 16-bit real mode,
;; only trashing RAX, BX, DS, RSP (preseved) and RIP.
;;
;; Caller puts the state to load in g_bs3CpuState64CtxToLoad, this function alters
;; the BX and RIP values before loading it.  It then switches to 16-bit real mode,
;; executes the worker given as input, re-enters long mode and saves the state to
;; g_bs3CpuState64CtxSaved.
;;
;; @param   rcx     Address of worker (16-bit) to invoke while in real-mode.
;;
BS3_PROC_BEGIN NAME(bs3CpuState64Worker)
        push    rbp
        mov     rbp, rsp
        sub     rsp, 40h
        mov     [rbp + 16], rcx

        ;
        ; Save the current register state so we can return with the exact state we entered.
        ;
        lea     rcx, [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64CtxCaller)) wrt FLAT]
        mov     [rsp], rcx
        call    NAME(Bs3RegCtxSave_c64)

        ;
        ; Load the context.  We modify the state to be loaded so that it fits
        ; into the code flow here..
        ;
        lea     rcx, [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64CtxToLoad)) wrt FLAT]
        mov     [rcx + BS3REGCTX.rsp], rsp
        ;lea     rdx, [BS3_WRT_RIP(.ctx_loaded) wrt FLAT] - absolute address cannot be relative. wtf?
        mov     edx, .ctx_loaded wrt FLAT
        mov     [rcx + BS3REGCTX.rip], rdx
        mov     edx, [rbp + 16]         ; Worker address. Putting it in the BX register relative to 16-bit CS.
        sub     edx, BS3_ADDR_BS3TEXT16
        mov     [rcx + BS3REGCTX.rbx], dx
        mov     edx, 0                  ; fFlags
        mov     [rsp], rcx
        mov     [rsp + 8], rdx
        call    NAME(Bs3RegCtxRestore_c64)
.ctx_loaded:

        ;
        ; Disable long mode.
        ;

        ; Construct a far return for switching to 16-bit code.
        push    BS3_SEL_R0_CS16
        push    .sixteen_bit_segment wrt CGROUP16
        xRETF
BS3_BEGIN_TEXT16
        BS3_SET_BITS 16
BS3_GLOBAL_LOCAL_LABEL .sixteen_bit_segment
        ; Make the DS usable from real mode.
        mov     ax, BS3_SEL_R0_DS16
        mov     ds, ax

        ; Exit to real mode.
        mov     eax, cr0
        and     eax, X86_CR0_NO_PE_NO_PG
        mov     cr0, eax
        jmp     CGROUP16:.reload_cs16
BS3_GLOBAL_LOCAL_LABEL .reload_cs16

        ;
        ; Jump to the 16-bit worker function that will make state modifications.
        ;
        jmp     bx
BS3_GLOBAL_LOCAL_LABEL .resume16

        ;
        ; Re-enter long mode.
        ;
        mov     eax, cr0
        or      eax, X86_CR0_PE | X86_CR0_PG
        mov     cr0, eax
        jmp     CGROUP16:.reload_cs_long_mode
BS3_GLOBAL_LOCAL_LABEL .reload_cs_long_mode
        ; Construct a far return for switching to 64-bit code.
        push    dword BS3_SEL_R0_CS64
        push    dword .sixtyfour_bit_segment wrt FLAT
        o32 retf
BS3_BEGIN_TEXT64
BS3_GLOBAL_LOCAL_LABEL .sixtyfour_bit_segment
        BS3_SET_BITS 64

        ;
        ; We're back in long mode, save the context.
        ;
        mov     [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64RCX)) wrt FLAT], rcx
        lea     rcx, [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64CtxSaved)) wrt FLAT]
        mov     [rsp], rcx
        call    NAME(Bs3RegCtxSave_c64)
        lea     rcx, [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64CtxSaved)) wrt FLAT]
        mov     rax, [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64RCX)) wrt FLAT]
        mov     [rcx + BS3REGCTX.rcx], rax

        ;
        ; Load the caller's context.
        ;
        lea     rcx, [BS3_WRT_RIP(BS3_DATA_NM(g_bs3CpuState64CtxCaller)) wrt FLAT]
        ;lea     rdx, [BS3_WRT_RIP(.return_sequence) wrt FLAT] - absolute address cannot be relative. wtf?
        mov     edx, .return_sequence wrt FLAT
        mov     [rcx + BS3REGCTX.rip], rdx
        mov     edx, 0
        mov     [rsp], rcx
        mov     [rsp + 8], rdx
        call    NAME(Bs3RegCtxRestore_c64)
.return_sequence:

        add     rsp, 40h
        pop     rbp
        ret
BS3_PROC_END   NAME(bs3CpuState64Worker)


BS3_BEGIN_TEXT16
;
; Real-mod modification workers for bs3CpuState64Worker.
;

BS3_PROC_BEGIN NAME(bs3CpuState64Worker_Nop)
        nop
        jmp     NAME(bs3CpuState64Worker.resume16)
BS3_PROC_END   NAME(bs3CpuState64Worker_Nop)


BS3_PROC_BEGIN NAME(bs3CpuState64Worker_ModAll32BitGrps)
        mov     eax, 0xc0ffee0d         ; C code hardcodes these values too.
        mov     ecx, 0xc0ffee1d
        mov     edx, 0xc0ffee2d
        mov     ebx, 0xc0ffee3d
        ; leave esp alone for now.
        mov     ebp, 0xc0ffee5d
        mov     esi, 0xc0ffee6d
        mov     edi, 0xc0ffee7d
        jmp     NAME(bs3CpuState64Worker.resume16)
BS3_PROC_END   NAME(bs3CpuState64Worker_ModAll32BitGrps)


BS3_PROC_BEGIN NAME(bs3CpuState64Worker_ModAll16BitGrps)
        mov     ax, 0xfad0         ; C code hardcodes these values too.
        mov     cx, 0xfad1
        mov     dx, 0xfad2
        mov     bx, 0xfad3
        ; leave esp alone for now.
        mov     bp, 0xfad5
        mov     si, 0xfad6
        mov     di, 0xfad7
        jmp     NAME(bs3CpuState64Worker.resume16)
BS3_PROC_END   NAME(bs3CpuState64Worker_ModAll16BitGrps)


BS3_PROC_BEGIN NAME(bs3CpuState64Worker_ModAll8BitGrps)
        mov     al, 0x10         ; C code hardcodes these values too.
        mov     ah, 0x11
        mov     cl, 0x20
        mov     ch, 0x21
        mov     dl, 0x30
        mov     dh, 0x31
        mov     bl, 0x40
        mov     bh, 0x41
        jmp     NAME(bs3CpuState64Worker.resume16)
BS3_PROC_END   NAME(bs3CpuState64Worker_ModAll8BitGrps)

BS3_PROC_BEGIN NAME(bs3CpuState64Worker_ModCr2)
        mov     eax, 0xf00dface ; C code hardcodes this value too.
        mov     cr2, eax
        jmp     NAME(bs3CpuState64Worker.resume16)
BS3_PROC_END   NAME(bs3CpuState64Worker_ModCr2)

;; @todo drX registers.