VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PATMA.asm@ 42062

Last change on this file since 42062 was 40007, checked in by vboxsync, 13 years ago

VMMR3/PATMA.asm: moved all patch records to the data section to prevent text relocations in the binary (thanks Mathias Krause!)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 71.7 KB
Line 
1; $Id: PATMA.asm 40007 2012-02-06 11:16:59Z vboxsync $
2;; @file
3; PATM Assembly Routines.
4;
5
6; Copyright (C) 2006-2007 Oracle Corporation
7;
8; This file is part of VirtualBox Open Source Edition (OSE), as
9; available from http://www.virtualbox.org. This file is free software;
10; you can redistribute it and/or modify it under the terms of the GNU
11; General Public License (GPL) as published by the Free Software
12; Foundation, in version 2 as it comes in the "COPYING" file of the
13; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15;
16
17;;
18; @note This method has problems in theory. If we fault for any reason, then we won't be able to restore
19; the guest's context properly!!
20; E.g if one of the push instructions causes a fault or SS isn't wide open and our patch GC state accesses aren't valid.
21; @assumptions
22; - Enough stack for a few pushes
23; - The SS selector has base 0 and limit 0xffffffff
24;
25; @todo stack probing is currently hardcoded and not present everywhere (search for 'probe stack')
26
27
28;*******************************************************************************
29;* Header Files *
30;*******************************************************************************
31%include "VBox/asmdefs.mac"
32%include "VBox/err.mac"
33%include "iprt/x86.mac"
34%include "VBox/vmm/vm.mac"
35%include "PATMA.mac"
36
37%ifdef DEBUG
38; Noisy, but useful for debugging certain problems
39;;;%define PATM_LOG_PATCHINSTR
40;;%define PATM_LOG_PATCHIRET
41%endif
42
43BEGINCONST
44
45%ifdef RT_ARCH_AMD64
46 BITS 32 ; switch to 32-bit mode (x86).
47%endif
48
49%ifdef VBOX_WITH_STATISTICS
50;
51; Patch call statistics
52;
53BEGINPROC PATMStats
54PATMStats_Start:
55 mov dword [ss:PATM_INTERRUPTFLAG], 0
56 pushf
57 inc dword [ss:PATM_ALLPATCHCALLS]
58 inc dword [ss:PATM_PERPATCHCALLS]
59 popf
60 mov dword [ss:PATM_INTERRUPTFLAG], 1
61PATMStats_End:
62ENDPROC PATMStats
63
64
65; Patch record for statistics
66GLOBALNAME PATMStatsRecord
67 RTCCPTR_DEF PATMStats_Start
68 DD 0
69 DD 0
70 DD 0
71 DD PATMStats_End - PATMStats_Start
72 DD 4
73 DD PATM_INTERRUPTFLAG
74 DD 0
75 DD PATM_ALLPATCHCALLS
76 DD 0
77 DD PATM_PERPATCHCALLS
78 DD 0
79 DD PATM_INTERRUPTFLAG
80 DD 0
81 DD 0ffffffffh
82%endif
83
84;
85; Set PATM_INTERRUPTFLAG
86;
87BEGINPROC PATMSetPIF
88PATMSetPIF_Start:
89 mov dword [ss:PATM_INTERRUPTFLAG], 1
90PATMSetPIF_End:
91ENDPROC PATMSetPIF
92
93
94SECTION .data
95; Patch record for setting PATM_INTERRUPTFLAG
96GLOBALNAME PATMSetPIFRecord
97 RTCCPTR_DEF PATMSetPIF_Start
98 DD 0
99 DD 0
100 DD 0
101 DD PATMSetPIF_End - PATMSetPIF_Start
102 DD 1
103 DD PATM_INTERRUPTFLAG
104 DD 0
105 DD 0ffffffffh
106SECTION .text
107
108;
109; Clear PATM_INTERRUPTFLAG
110;
111BEGINPROC PATMClearPIF
112PATMClearPIF_Start:
113 ; probe stack here as we can't recover from page faults later on
114 not dword [esp-64]
115 not dword [esp-64]
116 mov dword [ss:PATM_INTERRUPTFLAG], 0
117PATMClearPIF_End:
118ENDPROC PATMClearPIF
119
120
121SECTION .data
122; Patch record for clearing PATM_INTERRUPTFLAG
123GLOBALNAME PATMClearPIFRecord
124 RTCCPTR_DEF PATMClearPIF_Start
125 DD 0
126 DD 0
127 DD 0
128 DD PATMClearPIF_End - PATMClearPIF_Start
129 DD 1
130 DD PATM_INTERRUPTFLAG
131 DD 0
132 DD 0ffffffffh
133SECTION .text
134
135;
136; Clear PATM_INHIBITIRQADDR and fault if IF=0
137;
138BEGINPROC PATMClearInhibitIRQFaultIF0
139PATMClearInhibitIRQFaultIF0_Start:
140 mov dword [ss:PATM_INTERRUPTFLAG], 0
141 mov dword [ss:PATM_INHIBITIRQADDR], 0
142 pushf
143
144 test dword [ss:PATM_VMFLAGS], X86_EFL_IF
145 jz PATMClearInhibitIRQFaultIF0_Fault
146
147 ; if interrupts are pending, then we must go back to the host context to handle them!
148 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
149 jz PATMClearInhibitIRQFaultIF0_Continue
150
151 ; Go to our hypervisor trap handler to dispatch the pending irq
152 mov dword [ss:PATM_TEMP_EAX], eax
153 mov dword [ss:PATM_TEMP_ECX], ecx
154 mov dword [ss:PATM_TEMP_EDI], edi
155 mov dword [ss:PATM_TEMP_RESTORE_FLAGS], PATM_RESTORE_EAX | PATM_RESTORE_ECX | PATM_RESTORE_EDI
156 mov eax, PATM_ACTION_DISPATCH_PENDING_IRQ
157 lock or dword [ss:PATM_PENDINGACTION], eax
158 mov ecx, PATM_ACTION_MAGIC
159 mov edi, PATM_NEXTINSTRADDR
160 popfd ; restore flags we pushed above (the or instruction changes the flags as well)
161 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
162 ; does not return
163
164PATMClearInhibitIRQFaultIF0_Fault:
165 popf
166 mov dword [ss:PATM_INTERRUPTFLAG], 1
167 PATM_INT3
168
169PATMClearInhibitIRQFaultIF0_Continue:
170 popf
171 mov dword [ss:PATM_INTERRUPTFLAG], 1
172PATMClearInhibitIRQFaultIF0_End:
173ENDPROC PATMClearInhibitIRQFaultIF0
174
175
176SECTION .data
177; Patch record for clearing PATM_INHIBITIRQADDR
178GLOBALNAME PATMClearInhibitIRQFaultIF0Record
179 RTCCPTR_DEF PATMClearInhibitIRQFaultIF0_Start
180 DD 0
181 DD 0
182 DD 0
183 DD PATMClearInhibitIRQFaultIF0_End - PATMClearInhibitIRQFaultIF0_Start
184 DD 12
185 DD PATM_INTERRUPTFLAG
186 DD 0
187 DD PATM_INHIBITIRQADDR
188 DD 0
189 DD PATM_VMFLAGS
190 DD 0
191 DD PATM_VM_FORCEDACTIONS
192 DD 0
193 DD PATM_TEMP_EAX
194 DD 0
195 DD PATM_TEMP_ECX
196 DD 0
197 DD PATM_TEMP_EDI
198 DD 0
199 DD PATM_TEMP_RESTORE_FLAGS
200 DD 0
201 DD PATM_PENDINGACTION
202 DD 0
203 DD PATM_NEXTINSTRADDR
204 DD 0
205 DD PATM_INTERRUPTFLAG
206 DD 0
207 DD PATM_INTERRUPTFLAG
208 DD 0
209 DD 0ffffffffh
210SECTION .text
211
212;
213; Clear PATM_INHIBITIRQADDR and continue if IF=0 (duplicated function only; never jump back to guest code afterwards!!)
214;
215BEGINPROC PATMClearInhibitIRQContIF0
216PATMClearInhibitIRQContIF0_Start:
217 mov dword [ss:PATM_INTERRUPTFLAG], 0
218 mov dword [ss:PATM_INHIBITIRQADDR], 0
219 pushf
220
221 test dword [ss:PATM_VMFLAGS], X86_EFL_IF
222 jz PATMClearInhibitIRQContIF0_Continue
223
224 ; if interrupts are pending, then we must go back to the host context to handle them!
225 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
226 jz PATMClearInhibitIRQContIF0_Continue
227
228 ; Go to our hypervisor trap handler to dispatch the pending irq
229 mov dword [ss:PATM_TEMP_EAX], eax
230 mov dword [ss:PATM_TEMP_ECX], ecx
231 mov dword [ss:PATM_TEMP_EDI], edi
232 mov dword [ss:PATM_TEMP_RESTORE_FLAGS], PATM_RESTORE_EAX | PATM_RESTORE_ECX | PATM_RESTORE_EDI
233 mov eax, PATM_ACTION_DISPATCH_PENDING_IRQ
234 lock or dword [ss:PATM_PENDINGACTION], eax
235 mov ecx, PATM_ACTION_MAGIC
236 mov edi, PATM_NEXTINSTRADDR
237 popfd ; restore flags we pushed above (the or instruction changes the flags as well)
238 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
239 ; does not return
240
241PATMClearInhibitIRQContIF0_Continue:
242 popf
243 mov dword [ss:PATM_INTERRUPTFLAG], 1
244PATMClearInhibitIRQContIF0_End:
245ENDPROC PATMClearInhibitIRQContIF0
246
247
248SECTION .data
249; Patch record for clearing PATM_INHIBITIRQADDR
250GLOBALNAME PATMClearInhibitIRQContIF0Record
251 RTCCPTR_DEF PATMClearInhibitIRQContIF0_Start
252 DD 0
253 DD 0
254 DD 0
255 DD PATMClearInhibitIRQContIF0_End - PATMClearInhibitIRQContIF0_Start
256 DD 11
257 DD PATM_INTERRUPTFLAG
258 DD 0
259 DD PATM_INHIBITIRQADDR
260 DD 0
261 DD PATM_VMFLAGS
262 DD 0
263 DD PATM_VM_FORCEDACTIONS
264 DD 0
265 DD PATM_TEMP_EAX
266 DD 0
267 DD PATM_TEMP_ECX
268 DD 0
269 DD PATM_TEMP_EDI
270 DD 0
271 DD PATM_TEMP_RESTORE_FLAGS
272 DD 0
273 DD PATM_PENDINGACTION
274 DD 0
275 DD PATM_NEXTINSTRADDR
276 DD 0
277 DD PATM_INTERRUPTFLAG
278 DD 0
279 DD 0ffffffffh
280SECTION .text
281
282
283BEGINPROC PATMCliReplacement
284PATMCliStart:
285 mov dword [ss:PATM_INTERRUPTFLAG], 0
286 pushf
287%ifdef PATM_LOG_PATCHINSTR
288 push eax
289 push ecx
290 mov eax, PATM_ACTION_LOG_CLI
291 lock or dword [ss:PATM_PENDINGACTION], eax
292 mov ecx, PATM_ACTION_MAGIC
293 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
294 pop ecx
295 pop eax
296%endif
297
298 and dword [ss:PATM_VMFLAGS], ~X86_EFL_IF
299 popf
300
301 mov dword [ss:PATM_INTERRUPTFLAG], 1
302 DB 0xE9
303PATMCliJump:
304 DD PATM_JUMPDELTA
305PATMCliEnd:
306ENDPROC PATMCliReplacement
307
308
309SECTION .data
310; Patch record for 'cli'
311GLOBALNAME PATMCliRecord
312 RTCCPTR_DEF PATMCliStart
313 DD PATMCliJump - PATMCliStart
314 DD 0
315 DD 0
316 DD PATMCliEnd - PATMCliStart
317%ifdef PATM_LOG_PATCHINSTR
318 DD 4
319%else
320 DD 3
321%endif
322 DD PATM_INTERRUPTFLAG
323 DD 0
324%ifdef PATM_LOG_PATCHINSTR
325 DD PATM_PENDINGACTION
326 DD 0
327%endif
328 DD PATM_VMFLAGS
329 DD 0
330 DD PATM_INTERRUPTFLAG
331 DD 0
332 DD 0ffffffffh
333SECTION .text
334
335
336BEGINPROC PATMStiReplacement
337PATMStiStart:
338 mov dword [ss:PATM_INTERRUPTFLAG], 0
339 mov dword [ss:PATM_INHIBITIRQADDR], PATM_NEXTINSTRADDR
340 pushf
341%ifdef PATM_LOG_PATCHINSTR
342 push eax
343 push ecx
344 mov eax, PATM_ACTION_LOG_STI
345 lock or dword [ss:PATM_PENDINGACTION], eax
346 mov ecx, PATM_ACTION_MAGIC
347 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
348 pop ecx
349 pop eax
350%endif
351 or dword [ss:PATM_VMFLAGS], X86_EFL_IF
352 popf
353 mov dword [ss:PATM_INTERRUPTFLAG], 1
354PATMStiEnd:
355ENDPROC PATMStiReplacement
356
357SECTION .data
358; Patch record for 'sti'
359GLOBALNAME PATMStiRecord
360 RTCCPTR_DEF PATMStiStart
361 DD 0
362 DD 0
363 DD 0
364 DD PATMStiEnd - PATMStiStart
365%ifdef PATM_LOG_PATCHINSTR
366 DD 6
367%else
368 DD 5
369%endif
370 DD PATM_INTERRUPTFLAG
371 DD 0
372 DD PATM_INHIBITIRQADDR
373 DD 0
374 DD PATM_NEXTINSTRADDR
375 DD 0
376%ifdef PATM_LOG_PATCHINSTR
377 DD PATM_PENDINGACTION
378 DD 0
379%endif
380 DD PATM_VMFLAGS
381 DD 0
382 DD PATM_INTERRUPTFLAG
383 DD 0
384 DD 0ffffffffh
385SECTION .text
386
387;
388; Trampoline code for trap entry (without error code on the stack)
389;
390; esp + 32 - GS (V86 only)
391; esp + 28 - FS (V86 only)
392; esp + 24 - DS (V86 only)
393; esp + 20 - ES (V86 only)
394; esp + 16 - SS (if transfer to inner ring)
395; esp + 12 - ESP (if transfer to inner ring)
396; esp + 8 - EFLAGS
397; esp + 4 - CS
398; esp - EIP
399;
400BEGINPROC PATMTrapEntry
401PATMTrapEntryStart:
402 mov dword [ss:PATM_INTERRUPTFLAG], 0
403 pushf
404
405%ifdef PATM_LOG_PATCHIRET
406 push eax
407 push ecx
408 push edx
409 lea edx, dword [ss:esp+12+4] ;3 dwords + pushed flags -> iret eip
410 mov eax, PATM_ACTION_LOG_GATE_ENTRY
411 lock or dword [ss:PATM_PENDINGACTION], eax
412 mov ecx, PATM_ACTION_MAGIC
413 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
414 pop edx
415 pop ecx
416 pop eax
417%endif
418
419 test dword [esp+12], X86_EFL_VM
420 jnz PATMTrapNoRing1
421
422 ; make sure the saved CS selector for ring 1 is made 0
423 test dword [esp+8], 2
424 jnz PATMTrapNoRing1
425 test dword [esp+8], 1
426 jz PATMTrapNoRing1
427 and dword [esp+8], dword ~1 ; yasm / nasm dword
428PATMTrapNoRing1:
429
430 ; correct EFLAGS on the stack to include the current IOPL
431 push eax
432 mov eax, dword [ss:PATM_VMFLAGS]
433 and eax, X86_EFL_IOPL
434 and dword [esp+16], ~X86_EFL_IOPL ; esp+16 = eflags = esp+8+4(efl)+4(eax)
435 or dword [esp+16], eax
436 pop eax
437
438 popf
439 mov dword [ss:PATM_INTERRUPTFLAG], 1
440 DB 0xE9
441PATMTrapEntryJump:
442 DD PATM_JUMPDELTA
443PATMTrapEntryEnd:
444ENDPROC PATMTrapEntry
445
446
447SECTION .data
448; Patch record for trap gate entrypoint
449GLOBALNAME PATMTrapEntryRecord
450 RTCCPTR_DEF PATMTrapEntryStart
451 DD PATMTrapEntryJump - PATMTrapEntryStart
452 DD 0
453 DD 0
454 DD PATMTrapEntryEnd - PATMTrapEntryStart
455%ifdef PATM_LOG_PATCHIRET
456 DD 4
457%else
458 DD 3
459%endif
460 DD PATM_INTERRUPTFLAG
461 DD 0
462%ifdef PATM_LOG_PATCHIRET
463 DD PATM_PENDINGACTION
464 DD 0
465%endif
466 DD PATM_VMFLAGS
467 DD 0
468 DD PATM_INTERRUPTFLAG
469 DD 0
470 DD 0ffffffffh
471SECTION .text
472
473;
474; Trampoline code for trap entry (with error code on the stack)
475;
476; esp + 36 - GS (V86 only)
477; esp + 32 - FS (V86 only)
478; esp + 28 - DS (V86 only)
479; esp + 24 - ES (V86 only)
480; esp + 20 - SS (if transfer to inner ring)
481; esp + 16 - ESP (if transfer to inner ring)
482; esp + 12 - EFLAGS
483; esp + 8 - CS
484; esp + 4 - EIP
485; esp - error code
486;
487BEGINPROC PATMTrapEntryErrorCode
488PATMTrapErrorCodeEntryStart:
489 mov dword [ss:PATM_INTERRUPTFLAG], 0
490 pushf
491
492%ifdef PATM_LOG_PATCHIRET
493 push eax
494 push ecx
495 push edx
496 lea edx, dword [ss:esp+12+4+4] ;3 dwords + pushed flags + error code -> iret eip
497 mov eax, PATM_ACTION_LOG_GATE_ENTRY
498 lock or dword [ss:PATM_PENDINGACTION], eax
499 mov ecx, PATM_ACTION_MAGIC
500 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
501 pop edx
502 pop ecx
503 pop eax
504%endif
505
506 test dword [esp+16], X86_EFL_VM
507 jnz PATMTrapErrorCodeNoRing1
508
509 ; make sure the saved CS selector for ring 1 is made 0
510 test dword [esp+12], 2
511 jnz PATMTrapErrorCodeNoRing1
512 test dword [esp+12], 1
513 jz PATMTrapErrorCodeNoRing1
514 and dword [esp+12], dword ~1 ; yasm / nasm dword
515PATMTrapErrorCodeNoRing1:
516
517 ; correct EFLAGS on the stack to include the current IOPL
518 push eax
519 mov eax, dword [ss:PATM_VMFLAGS]
520 and eax, X86_EFL_IOPL
521 and dword [esp+20], ~X86_EFL_IOPL ; esp+20 = eflags = esp+8+4(efl)+4(error code)+4(eax)
522 or dword [esp+20], eax
523 pop eax
524
525 popf
526 mov dword [ss:PATM_INTERRUPTFLAG], 1
527 DB 0xE9
528PATMTrapErrorCodeEntryJump:
529 DD PATM_JUMPDELTA
530PATMTrapErrorCodeEntryEnd:
531ENDPROC PATMTrapEntryErrorCode
532
533
534SECTION .data
535; Patch record for trap gate entrypoint
536GLOBALNAME PATMTrapEntryRecordErrorCode
537 RTCCPTR_DEF PATMTrapErrorCodeEntryStart
538 DD PATMTrapErrorCodeEntryJump - PATMTrapErrorCodeEntryStart
539 DD 0
540 DD 0
541 DD PATMTrapErrorCodeEntryEnd - PATMTrapErrorCodeEntryStart
542%ifdef PATM_LOG_PATCHIRET
543 DD 4
544%else
545 DD 3
546%endif
547 DD PATM_INTERRUPTFLAG
548 DD 0
549%ifdef PATM_LOG_PATCHIRET
550 DD PATM_PENDINGACTION
551 DD 0
552%endif
553 DD PATM_VMFLAGS
554 DD 0
555 DD PATM_INTERRUPTFLAG
556 DD 0
557 DD 0ffffffffh
558SECTION .text
559
560
561;
562; Trampoline code for interrupt gate entry (without error code on the stack)
563;
564; esp + 32 - GS (V86 only)
565; esp + 28 - FS (V86 only)
566; esp + 24 - DS (V86 only)
567; esp + 20 - ES (V86 only)
568; esp + 16 - SS (if transfer to inner ring)
569; esp + 12 - ESP (if transfer to inner ring)
570; esp + 8 - EFLAGS
571; esp + 4 - CS
572; esp - EIP
573;
574BEGINPROC PATMIntEntry
575PATMIntEntryStart:
576 mov dword [ss:PATM_INTERRUPTFLAG], 0
577 pushf
578
579%ifdef PATM_LOG_PATCHIRET
580 push eax
581 push ecx
582 push edx
583 lea edx, dword [ss:esp+12+4] ;3 dwords + pushed flags -> iret eip
584 mov eax, PATM_ACTION_LOG_GATE_ENTRY
585 lock or dword [ss:PATM_PENDINGACTION], eax
586 mov ecx, PATM_ACTION_MAGIC
587 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
588 pop edx
589 pop ecx
590 pop eax
591%endif
592
593 test dword [esp+12], X86_EFL_VM
594 jnz PATMIntNoRing1
595
596 ; make sure the saved CS selector for ring 1 is made 0
597 test dword [esp+8], 2
598 jnz PATMIntNoRing1
599 test dword [esp+8], 1
600 jz PATMIntNoRing1
601 and dword [esp+8], dword ~1 ; yasm / nasm dword
602PATMIntNoRing1:
603
604 ; correct EFLAGS on the stack to include the current IOPL
605 push eax
606 mov eax, dword [ss:PATM_VMFLAGS]
607 and eax, X86_EFL_IOPL
608 and dword [esp+16], ~X86_EFL_IOPL ; esp+16 = eflags = esp+8+4(efl)+4(eax)
609 or dword [esp+16], eax
610 pop eax
611
612 popf
613 mov dword [ss:PATM_INTERRUPTFLAG], 1
614PATMIntEntryEnd:
615ENDPROC PATMIntEntry
616
617
618SECTION .data
619; Patch record for interrupt gate entrypoint
620GLOBALNAME PATMIntEntryRecord
621 RTCCPTR_DEF PATMIntEntryStart
622 DD 0
623 DD 0
624 DD 0
625 DD PATMIntEntryEnd - PATMIntEntryStart
626%ifdef PATM_LOG_PATCHIRET
627 DD 4
628%else
629 DD 3
630%endif
631 DD PATM_INTERRUPTFLAG
632 DD 0
633%ifdef PATM_LOG_PATCHIRET
634 DD PATM_PENDINGACTION
635 DD 0
636%endif
637 DD PATM_VMFLAGS
638 DD 0
639 DD PATM_INTERRUPTFLAG
640 DD 0
641 DD 0ffffffffh
642SECTION .text
643
644;
645; Trampoline code for interrupt gate entry (*with* error code on the stack)
646;
647; esp + 36 - GS (V86 only)
648; esp + 32 - FS (V86 only)
649; esp + 28 - DS (V86 only)
650; esp + 24 - ES (V86 only)
651; esp + 20 - SS (if transfer to inner ring)
652; esp + 16 - ESP (if transfer to inner ring)
653; esp + 12 - EFLAGS
654; esp + 8 - CS
655; esp + 4 - EIP
656; esp - error code
657;
658BEGINPROC PATMIntEntryErrorCode
659PATMIntEntryErrorCodeStart:
660 mov dword [ss:PATM_INTERRUPTFLAG], 0
661 pushf
662
663%ifdef PATM_LOG_PATCHIRET
664 push eax
665 push ecx
666 push edx
667 lea edx, dword [ss:esp+12+4+4] ;3 dwords + pushed flags + error code -> iret eip
668 mov eax, PATM_ACTION_LOG_GATE_ENTRY
669 lock or dword [ss:PATM_PENDINGACTION], eax
670 mov ecx, PATM_ACTION_MAGIC
671 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
672 pop edx
673 pop ecx
674 pop eax
675%endif
676
677 test dword [esp+16], X86_EFL_VM
678 jnz PATMIntNoRing1_ErrorCode
679
680 ; make sure the saved CS selector for ring 1 is made 0
681 test dword [esp+12], 2
682 jnz PATMIntNoRing1_ErrorCode
683 test dword [esp+12], 1
684 jz PATMIntNoRing1_ErrorCode
685 and dword [esp+12], dword ~1 ; yasm / nasm dword
686PATMIntNoRing1_ErrorCode:
687
688 ; correct EFLAGS on the stack to include the current IOPL
689 push eax
690 mov eax, dword [ss:PATM_VMFLAGS]
691 and eax, X86_EFL_IOPL
692 and dword [esp+20], ~X86_EFL_IOPL ; esp+20 = eflags = esp+8+4(efl)+4(eax)+4(error code)
693 or dword [esp+20], eax
694 pop eax
695
696 popf
697 mov dword [ss:PATM_INTERRUPTFLAG], 1
698PATMIntEntryErrorCodeEnd:
699ENDPROC PATMIntEntryErrorCode
700
701
702SECTION .data
703; Patch record for interrupt gate entrypoint
704GLOBALNAME PATMIntEntryRecordErrorCode
705 RTCCPTR_DEF PATMIntEntryErrorCodeStart
706 DD 0
707 DD 0
708 DD 0
709 DD PATMIntEntryErrorCodeEnd - PATMIntEntryErrorCodeStart
710%ifdef PATM_LOG_PATCHIRET
711 DD 4
712%else
713 DD 3
714%endif
715 DD PATM_INTERRUPTFLAG
716 DD 0
717%ifdef PATM_LOG_PATCHIRET
718 DD PATM_PENDINGACTION
719 DD 0
720%endif
721 DD PATM_VMFLAGS
722 DD 0
723 DD PATM_INTERRUPTFLAG
724 DD 0
725 DD 0ffffffffh
726SECTION .text
727
728;
729; 32 bits Popf replacement that faults when IF remains 0
730;
731BEGINPROC PATMPopf32Replacement
732PATMPopf32Start:
733 mov dword [ss:PATM_INTERRUPTFLAG], 0
734%ifdef PATM_LOG_PATCHINSTR
735 push eax
736 push ecx
737 mov eax, PATM_ACTION_LOG_POPF_IF1
738 test dword [esp+8], X86_EFL_IF
739 jnz PATMPopf32_Log
740 mov eax, PATM_ACTION_LOG_POPF_IF0
741
742PATMPopf32_Log:
743 lock or dword [ss:PATM_PENDINGACTION], eax
744 mov ecx, PATM_ACTION_MAGIC
745 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
746 pop ecx
747 pop eax
748%endif
749
750 test dword [esp], X86_EFL_IF
751 jnz PATMPopf32_Ok
752 mov dword [ss:PATM_INTERRUPTFLAG], 1
753 PATM_INT3
754
755PATMPopf32_Ok:
756 ; Note: we don't allow popf instructions to change the current IOPL; we simply ignore such changes (!!!)
757 ; In this particular patch it's rather unlikely the pushf was included, so we have no way to check if the flags on the stack were correctly synced
758 ; PATMPopf32Replacement_NoExit is different, because it's only used in IDT and function patches
759 or dword [ss:PATM_VMFLAGS], X86_EFL_IF
760
761 ; if interrupts are pending, then we must go back to the host context to handle them!
762 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
763 jz PATMPopf32_Continue
764
765 ; Go to our hypervisor trap handler to dispatch the pending irq
766 mov dword [ss:PATM_TEMP_EAX], eax
767 mov dword [ss:PATM_TEMP_ECX], ecx
768 mov dword [ss:PATM_TEMP_EDI], edi
769 mov dword [ss:PATM_TEMP_RESTORE_FLAGS], PATM_RESTORE_EAX | PATM_RESTORE_ECX | PATM_RESTORE_EDI
770 mov eax, PATM_ACTION_DISPATCH_PENDING_IRQ
771 lock or dword [ss:PATM_PENDINGACTION], eax
772 mov ecx, PATM_ACTION_MAGIC
773 mov edi, PATM_NEXTINSTRADDR
774
775 popfd ; restore flags we pushed above (the or instruction changes the flags as well)
776 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
777 ; does not return
778
779PATMPopf32_Continue:
780 popfd ; restore flags we pushed above
781 mov dword [ss:PATM_INTERRUPTFLAG], 1
782 DB 0xE9
783PATMPopf32Jump:
784 DD PATM_JUMPDELTA
785PATMPopf32End:
786ENDPROC PATMPopf32Replacement
787
788
789SECTION .data
790; Patch record for 'popfd'
791GLOBALNAME PATMPopf32Record
792 RTCCPTR_DEF PATMPopf32Start
793 DD PATMPopf32Jump - PATMPopf32Start
794 DD 0
795 DD 0
796 DD PATMPopf32End - PATMPopf32Start
797%ifdef PATM_LOG_PATCHINSTR
798 DD 12
799%else
800 DD 11
801%endif
802 DD PATM_INTERRUPTFLAG
803 DD 0
804%ifdef PATM_LOG_PATCHINSTR
805 DD PATM_PENDINGACTION
806 DD 0
807%endif
808 DD PATM_INTERRUPTFLAG
809 DD 0
810 DD PATM_VMFLAGS
811 DD 0
812 DD PATM_VM_FORCEDACTIONS
813 DD 0
814 DD PATM_TEMP_EAX
815 DD 0
816 DD PATM_TEMP_ECX
817 DD 0
818 DD PATM_TEMP_EDI
819 DD 0
820 DD PATM_TEMP_RESTORE_FLAGS
821 DD 0
822 DD PATM_PENDINGACTION
823 DD 0
824 DD PATM_NEXTINSTRADDR
825 DD 0
826 DD PATM_INTERRUPTFLAG
827 DD 0
828 DD 0ffffffffh
829SECTION .text
830
831; no need to check the IF flag when popf isn't an exit point of a patch (e.g. function duplication)
832BEGINPROC PATMPopf32Replacement_NoExit
833PATMPopf32_NoExitStart:
834 mov dword [ss:PATM_INTERRUPTFLAG], 0
835%ifdef PATM_LOG_PATCHINSTR
836 push eax
837 push ecx
838 mov eax, PATM_ACTION_LOG_POPF_IF1
839 test dword [esp+8], X86_EFL_IF
840 jnz PATMPopf32_NoExitLog
841 mov eax, PATM_ACTION_LOG_POPF_IF0
842
843PATMPopf32_NoExitLog:
844 lock or dword [ss:PATM_PENDINGACTION], eax
845 mov ecx, PATM_ACTION_MAGIC
846 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
847 pop ecx
848 pop eax
849%endif
850 test dword [esp], X86_EFL_IF
851 jz PATMPopf32_NoExit_Continue
852
853 ; if interrupts are pending, then we must go back to the host context to handle them!
854 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
855 jz PATMPopf32_NoExit_Continue
856
857 ; Go to our hypervisor trap handler to dispatch the pending irq
858 mov dword [ss:PATM_TEMP_EAX], eax
859 mov dword [ss:PATM_TEMP_ECX], ecx
860 mov dword [ss:PATM_TEMP_EDI], edi
861 mov dword [ss:PATM_TEMP_RESTORE_FLAGS], PATM_RESTORE_EAX | PATM_RESTORE_ECX | PATM_RESTORE_EDI
862 mov eax, PATM_ACTION_DISPATCH_PENDING_IRQ
863 lock or dword [ss:PATM_PENDINGACTION], eax
864 mov ecx, PATM_ACTION_MAGIC
865 mov edi, PATM_NEXTINSTRADDR
866
867 pop dword [ss:PATM_VMFLAGS] ; restore flags now (the or instruction changes the flags as well)
868 push dword [ss:PATM_VMFLAGS]
869 popfd
870
871 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
872 ; does not return
873
874PATMPopf32_NoExit_Continue:
875 pop dword [ss:PATM_VMFLAGS]
876 push dword [ss:PATM_VMFLAGS]
877 popfd
878 mov dword [ss:PATM_INTERRUPTFLAG], 1
879PATMPopf32_NoExitEnd:
880ENDPROC PATMPopf32Replacement_NoExit
881
882
883SECTION .data
884; Patch record for 'popfd'
885GLOBALNAME PATMPopf32Record_NoExit
886 RTCCPTR_DEF PATMPopf32_NoExitStart
887 DD 0
888 DD 0
889 DD 0
890 DD PATMPopf32_NoExitEnd - PATMPopf32_NoExitStart
891%ifdef PATM_LOG_PATCHINSTR
892 DD 14
893%else
894 DD 13
895%endif
896 DD PATM_INTERRUPTFLAG
897 DD 0
898%ifdef PATM_LOG_PATCHINSTR
899 DD PATM_PENDINGACTION
900 DD 0
901%endif
902 DD PATM_VM_FORCEDACTIONS
903 DD 0
904 DD PATM_TEMP_EAX
905 DD 0
906 DD PATM_TEMP_ECX
907 DD 0
908 DD PATM_TEMP_EDI
909 DD 0
910 DD PATM_TEMP_RESTORE_FLAGS
911 DD 0
912 DD PATM_PENDINGACTION
913 DD 0
914 DD PATM_NEXTINSTRADDR
915 DD 0
916 DD PATM_VMFLAGS
917 DD 0
918 DD PATM_VMFLAGS
919 DD 0
920 DD PATM_VMFLAGS
921 DD 0
922 DD PATM_VMFLAGS
923 DD 0
924 DD PATM_INTERRUPTFLAG
925 DD 0
926 DD 0ffffffffh
927SECTION .text
928
929
930;
931; 16 bits Popf replacement that faults when IF remains 0
932;
933BEGINPROC PATMPopf16Replacement
934PATMPopf16Start:
935 mov dword [ss:PATM_INTERRUPTFLAG], 0
936 test word [esp], X86_EFL_IF
937 jnz PATMPopf16_Ok
938 mov dword [ss:PATM_INTERRUPTFLAG], 1
939 PATM_INT3
940
941PATMPopf16_Ok:
942 ; if interrupts are pending, then we must go back to the host context to handle them!
943 ; @note we destroy the flags here, but that should really not matter (PATM_INT3 case)
944 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
945 jz PATMPopf16_Continue
946 mov dword [ss:PATM_INTERRUPTFLAG], 1
947 PATM_INT3
948
949PATMPopf16_Continue:
950
951 pop word [ss:PATM_VMFLAGS]
952 push word [ss:PATM_VMFLAGS]
953 and dword [ss:PATM_VMFLAGS], PATM_VIRTUAL_FLAGS_MASK
954 or dword [ss:PATM_VMFLAGS], PATM_VIRTUAL_FLAGS_MASK
955
956 DB 0x66 ; size override
957 popf ;after the and and or operations!! (flags must be preserved)
958 mov dword [ss:PATM_INTERRUPTFLAG], 1
959
960 DB 0xE9
961PATMPopf16Jump:
962 DD PATM_JUMPDELTA
963PATMPopf16End:
964ENDPROC PATMPopf16Replacement
965
966
967SECTION .data
968; Patch record for 'popf'
969GLOBALNAME PATMPopf16Record
970 RTCCPTR_DEF PATMPopf16Start
971 DD PATMPopf16Jump - PATMPopf16Start
972 DD 0
973 DD 0
974 DD PATMPopf16End - PATMPopf16Start
975 DD 9
976 DD PATM_INTERRUPTFLAG
977 DD 0
978 DD PATM_INTERRUPTFLAG
979 DD 0
980 DD PATM_VM_FORCEDACTIONS
981 DD 0
982 DD PATM_INTERRUPTFLAG
983 DD 0
984 DD PATM_VMFLAGS
985 DD 0
986 DD PATM_VMFLAGS
987 DD 0
988 DD PATM_VMFLAGS
989 DD 0
990 DD PATM_VMFLAGS
991 DD 0
992 DD PATM_INTERRUPTFLAG
993 DD 0
994 DD 0ffffffffh
995SECTION .text
996
997;
998; 16 bits Popf replacement that faults when IF remains 0
999; @todo not necessary to fault in that case (see 32 bits version)
1000BEGINPROC PATMPopf16Replacement_NoExit
1001PATMPopf16Start_NoExit:
1002 mov dword [ss:PATM_INTERRUPTFLAG], 0
1003 test word [esp], X86_EFL_IF
1004 jnz PATMPopf16_Ok_NoExit
1005 mov dword [ss:PATM_INTERRUPTFLAG], 1
1006 PATM_INT3
1007
1008PATMPopf16_Ok_NoExit:
1009 ; if interrupts are pending, then we must go back to the host context to handle them!
1010 ; @note we destroy the flags here, but that should really not matter (PATM_INT3 case)
1011 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
1012 jz PATMPopf16_Continue_NoExit
1013 mov dword [ss:PATM_INTERRUPTFLAG], 1
1014 PATM_INT3
1015
1016PATMPopf16_Continue_NoExit:
1017
1018 pop word [ss:PATM_VMFLAGS]
1019 push word [ss:PATM_VMFLAGS]
1020 and dword [ss:PATM_VMFLAGS], PATM_VIRTUAL_FLAGS_MASK
1021 or dword [ss:PATM_VMFLAGS], PATM_VIRTUAL_FLAGS_MASK
1022
1023 DB 0x66 ; size override
1024 popf ;after the and and or operations!! (flags must be preserved)
1025 mov dword [ss:PATM_INTERRUPTFLAG], 1
1026PATMPopf16End_NoExit:
1027ENDPROC PATMPopf16Replacement_NoExit
1028
1029
1030SECTION .data
1031; Patch record for 'popf'
1032GLOBALNAME PATMPopf16Record_NoExit
1033 RTCCPTR_DEF PATMPopf16Start_NoExit
1034 DD 0
1035 DD 0
1036 DD 0
1037 DD PATMPopf16End_NoExit - PATMPopf16Start_NoExit
1038 DD 9
1039 DD PATM_INTERRUPTFLAG
1040 DD 0
1041 DD PATM_INTERRUPTFLAG
1042 DD 0
1043 DD PATM_VM_FORCEDACTIONS
1044 DD 0
1045 DD PATM_INTERRUPTFLAG
1046 DD 0
1047 DD PATM_VMFLAGS
1048 DD 0
1049 DD PATM_VMFLAGS
1050 DD 0
1051 DD PATM_VMFLAGS
1052 DD 0
1053 DD PATM_VMFLAGS
1054 DD 0
1055 DD PATM_INTERRUPTFLAG
1056 DD 0
1057 DD 0ffffffffh
1058SECTION .text
1059
1060
1061BEGINPROC PATMPushf32Replacement
1062PATMPushf32Start:
1063 mov dword [ss:PATM_INTERRUPTFLAG], 0
1064 pushfd
1065%ifdef PATM_LOG_PATCHINSTR
1066 push eax
1067 push ecx
1068 mov eax, PATM_ACTION_LOG_PUSHF
1069 lock or dword [ss:PATM_PENDINGACTION], eax
1070 mov ecx, PATM_ACTION_MAGIC
1071 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1072 pop ecx
1073 pop eax
1074%endif
1075
1076 pushfd
1077 push eax
1078 mov eax, dword [esp+8]
1079 and eax, PATM_FLAGS_MASK
1080 or eax, dword [ss:PATM_VMFLAGS]
1081 mov dword [esp+8], eax
1082 pop eax
1083 popfd
1084 mov dword [ss:PATM_INTERRUPTFLAG], 1
1085PATMPushf32End:
1086ENDPROC PATMPushf32Replacement
1087
1088
1089SECTION .data
1090; Patch record for 'pushfd'
1091GLOBALNAME PATMPushf32Record
1092 RTCCPTR_DEF PATMPushf32Start
1093 DD 0
1094 DD 0
1095 DD 0
1096 DD PATMPushf32End - PATMPushf32Start
1097%ifdef PATM_LOG_PATCHINSTR
1098 DD 4
1099%else
1100 DD 3
1101%endif
1102 DD PATM_INTERRUPTFLAG
1103 DD 0
1104%ifdef PATM_LOG_PATCHINSTR
1105 DD PATM_PENDINGACTION
1106 DD 0
1107%endif
1108 DD PATM_VMFLAGS
1109 DD 0
1110 DD PATM_INTERRUPTFLAG
1111 DD 0
1112 DD 0ffffffffh
1113SECTION .text
1114
1115
1116BEGINPROC PATMPushf16Replacement
1117PATMPushf16Start:
1118 mov dword [ss:PATM_INTERRUPTFLAG], 0
1119 DB 0x66 ; size override
1120 pushf
1121 DB 0x66 ; size override
1122 pushf
1123 push eax
1124 xor eax, eax
1125 mov ax, word [esp+6]
1126 and eax, PATM_FLAGS_MASK
1127 or eax, dword [ss:PATM_VMFLAGS]
1128 mov word [esp+6], ax
1129 pop eax
1130
1131 DB 0x66 ; size override
1132 popf
1133 mov dword [ss:PATM_INTERRUPTFLAG], 1
1134PATMPushf16End:
1135ENDPROC PATMPushf16Replacement
1136
1137
1138SECTION .data
1139; Patch record for 'pushf'
1140GLOBALNAME PATMPushf16Record
1141 RTCCPTR_DEF PATMPushf16Start
1142 DD 0
1143 DD 0
1144 DD 0
1145 DD PATMPushf16End - PATMPushf16Start
1146 DD 3
1147 DD PATM_INTERRUPTFLAG
1148 DD 0
1149 DD PATM_VMFLAGS
1150 DD 0
1151 DD PATM_INTERRUPTFLAG
1152 DD 0
1153 DD 0ffffffffh
1154SECTION .text
1155
1156
1157BEGINPROC PATMPushCSReplacement
1158PATMPushCSStart:
1159 mov dword [ss:PATM_INTERRUPTFLAG], 0
1160 push cs
1161 pushfd
1162
1163 test dword [esp+4], 2
1164 jnz pushcs_notring1
1165
1166 ; change dpl from 1 to 0
1167 and dword [esp+4], dword ~1 ; yasm / nasm dword
1168
1169pushcs_notring1:
1170 popfd
1171
1172 mov dword [ss:PATM_INTERRUPTFLAG], 1
1173 DB 0xE9
1174PATMPushCSJump:
1175 DD PATM_JUMPDELTA
1176PATMPushCSEnd:
1177ENDPROC PATMPushCSReplacement
1178
1179
1180SECTION .data
1181; Patch record for 'push cs'
1182GLOBALNAME PATMPushCSRecord
1183 RTCCPTR_DEF PATMPushCSStart
1184 DD PATMPushCSJump - PATMPushCSStart
1185 DD 0
1186 DD 0
1187 DD PATMPushCSEnd - PATMPushCSStart
1188 DD 2
1189 DD PATM_INTERRUPTFLAG
1190 DD 0
1191 DD PATM_INTERRUPTFLAG
1192 DD 0
1193 DD 0ffffffffh
1194SECTION .text
1195
1196;;****************************************************
1197;; Abstract:
1198;;
1199;; if eflags.NT==0 && iretstack.eflags.VM==0 && iretstack.eflags.IOPL==0
1200;; then
1201;; if return to ring 0 (iretstack.new_cs & 3 == 0)
1202;; then
1203;; if iretstack.new_eflags.IF == 1 && iretstack.new_eflags.IOPL == 0
1204;; then
1205;; iretstack.new_cs |= 1
1206;; else
1207;; int 3
1208;; endif
1209;; uVMFlags &= ~X86_EFL_IF
1210;; iret
1211;; else
1212;; int 3
1213;;****************************************************
1214;;
1215; Stack:
1216;
1217; esp + 32 - GS (V86 only)
1218; esp + 28 - FS (V86 only)
1219; esp + 24 - DS (V86 only)
1220; esp + 20 - ES (V86 only)
1221; esp + 16 - SS (if transfer to outer ring)
1222; esp + 12 - ESP (if transfer to outer ring)
1223; esp + 8 - EFLAGS
1224; esp + 4 - CS
1225; esp - EIP
1226;;
1227BEGINPROC PATMIretReplacement
1228PATMIretStart:
1229 mov dword [ss:PATM_INTERRUPTFLAG], 0
1230 pushfd
1231
1232%ifdef PATM_LOG_PATCHIRET
1233 push eax
1234 push ecx
1235 push edx
1236 lea edx, dword [ss:esp+12+4] ;3 dwords + pushed flags -> iret eip
1237 mov eax, PATM_ACTION_LOG_IRET
1238 lock or dword [ss:PATM_PENDINGACTION], eax
1239 mov ecx, PATM_ACTION_MAGIC
1240 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1241 pop edx
1242 pop ecx
1243 pop eax
1244%endif
1245
1246 test dword [esp], X86_EFL_NT
1247 jnz near iret_fault1
1248
1249 ; we can't do an iret to v86 code, as we run with CPL=1. The iret would attempt a protected mode iret and (most likely) fault.
1250 test dword [esp+12], X86_EFL_VM
1251 jnz near iret_return_to_v86
1252
1253 ;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1254 ;;@todo: not correct for iret back to ring 2!!!!!
1255 ;;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1256
1257 test dword [esp+8], 2
1258 jnz iret_notring0
1259
1260 test dword [esp+12], X86_EFL_IF
1261 jz near iret_clearIF
1262
1263 ; force ring 1 CS RPL
1264 or dword [esp+8], 1
1265iret_notring0:
1266
1267; if interrupts are pending, then we must go back to the host context to handle them!
1268; Note: This is very important as pending pic interrupts can be overridden by apic interrupts if we don't check early enough (Fedora 5 boot)
1269; @@todo fix this properly, so we can dispatch pending interrupts in GC
1270 test dword [ss:PATM_VM_FORCEDACTIONS], VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC
1271 jz iret_continue
1272
1273; Go to our hypervisor trap handler to dispatch the pending irq
1274 mov dword [ss:PATM_TEMP_EAX], eax
1275 mov dword [ss:PATM_TEMP_ECX], ecx
1276 mov dword [ss:PATM_TEMP_EDI], edi
1277 mov dword [ss:PATM_TEMP_RESTORE_FLAGS], PATM_RESTORE_EAX | PATM_RESTORE_ECX | PATM_RESTORE_EDI
1278 mov eax, PATM_ACTION_PENDING_IRQ_AFTER_IRET
1279 lock or dword [ss:PATM_PENDINGACTION], eax
1280 mov ecx, PATM_ACTION_MAGIC
1281 mov edi, PATM_CURINSTRADDR
1282
1283 popfd
1284 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1285 ; does not return
1286
1287iret_continue :
1288 ; This section must *always* be executed (!!)
1289 ; Extract the IOPL from the return flags, save them to our virtual flags and
1290 ; put them back to zero
1291 ; @note we assume iretd doesn't fault!!!
1292 push eax
1293 mov eax, dword [esp+16]
1294 and eax, X86_EFL_IOPL
1295 and dword [ss:PATM_VMFLAGS], ~X86_EFL_IOPL
1296 or dword [ss:PATM_VMFLAGS], eax
1297 pop eax
1298 and dword [esp+12], ~X86_EFL_IOPL
1299
1300 ; Set IF again; below we make sure this won't cause problems.
1301 or dword [ss:PATM_VMFLAGS], X86_EFL_IF
1302
1303 ; make sure iret is executed fully (including the iret below; cli ... iret can otherwise be interrupted)
1304 mov dword [ss:PATM_INHIBITIRQADDR], PATM_CURINSTRADDR
1305
1306 popfd
1307 mov dword [ss:PATM_INTERRUPTFLAG], 1
1308 iretd
1309 PATM_INT3
1310
1311iret_fault:
1312 popfd
1313 mov dword [ss:PATM_INTERRUPTFLAG], 1
1314 PATM_INT3
1315
1316iret_fault1:
1317 nop
1318 popfd
1319 mov dword [ss:PATM_INTERRUPTFLAG], 1
1320 PATM_INT3
1321
1322iret_clearIF:
1323 push dword [esp+4] ; eip to return to
1324 pushfd
1325 push eax
1326 push PATM_FIXUP
1327 DB 0E8h ; call
1328 DD PATM_IRET_FUNCTION
1329 add esp, 4 ; pushed address of jump table
1330
1331 cmp eax, 0
1332 je near iret_fault3
1333
1334 mov dword [esp+12+4], eax ; stored eip in iret frame
1335 pop eax
1336 popfd
1337 add esp, 4 ; pushed eip
1338
1339 ; always ring 0 return -> change to ring 1 (CS in iret frame)
1340 or dword [esp+8], 1
1341
1342 ; This section must *always* be executed (!!)
1343 ; Extract the IOPL from the return flags, save them to our virtual flags and
1344 ; put them back to zero
1345 push eax
1346 mov eax, dword [esp+16]
1347 and eax, X86_EFL_IOPL
1348 and dword [ss:PATM_VMFLAGS], ~X86_EFL_IOPL
1349 or dword [ss:PATM_VMFLAGS], eax
1350 pop eax
1351 and dword [esp+12], ~X86_EFL_IOPL
1352
1353 ; Clear IF
1354 and dword [ss:PATM_VMFLAGS], ~X86_EFL_IF
1355 popfd
1356
1357 ; the patched destination code will set PATM_INTERRUPTFLAG after the return!
1358 iretd
1359
1360iret_return_to_v86:
1361 test dword [esp+12], X86_EFL_IF
1362 jz iret_fault
1363
1364 ; Go to our hypervisor trap handler to perform the iret to v86 code
1365 mov dword [ss:PATM_TEMP_EAX], eax
1366 mov dword [ss:PATM_TEMP_ECX], ecx
1367 mov dword [ss:PATM_TEMP_RESTORE_FLAGS], PATM_RESTORE_EAX | PATM_RESTORE_ECX
1368 mov eax, PATM_ACTION_DO_V86_IRET
1369 lock or dword [ss:PATM_PENDINGACTION], eax
1370 mov ecx, PATM_ACTION_MAGIC
1371
1372 popfd
1373
1374 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1375 ; does not return
1376
1377
1378iret_fault3:
1379 pop eax
1380 popfd
1381 add esp, 4 ; pushed eip
1382 jmp iret_fault
1383
1384align 4
1385PATMIretTable:
1386 DW PATM_MAX_JUMPTABLE_ENTRIES ; nrSlots
1387 DW 0 ; ulInsertPos
1388 DD 0 ; cAddresses
1389 TIMES PATCHJUMPTABLE_SIZE DB 0 ; lookup slots
1390
1391PATMIretEnd:
1392ENDPROC PATMIretReplacement
1393
1394SECTION .data
1395; Patch record for 'iretd'
1396GLOBALNAME PATMIretRecord
1397 RTCCPTR_DEF PATMIretStart
1398 DD 0
1399 DD 0
1400 DD 0
1401 DD PATMIretEnd- PATMIretStart
1402%ifdef PATM_LOG_PATCHIRET
1403 DD 26
1404%else
1405 DD 25
1406%endif
1407 DD PATM_INTERRUPTFLAG
1408 DD 0
1409%ifdef PATM_LOG_PATCHIRET
1410 DD PATM_PENDINGACTION
1411 DD 0
1412%endif
1413 DD PATM_VM_FORCEDACTIONS
1414 DD 0
1415 DD PATM_TEMP_EAX
1416 DD 0
1417 DD PATM_TEMP_ECX
1418 DD 0
1419 DD PATM_TEMP_EDI
1420 DD 0
1421 DD PATM_TEMP_RESTORE_FLAGS
1422 DD 0
1423 DD PATM_PENDINGACTION
1424 DD 0
1425 DD PATM_CURINSTRADDR
1426 DD 0
1427 DD PATM_VMFLAGS
1428 DD 0
1429 DD PATM_VMFLAGS
1430 DD 0
1431 DD PATM_VMFLAGS
1432 DD 0
1433 DD PATM_INHIBITIRQADDR
1434 DD 0
1435 DD PATM_CURINSTRADDR
1436 DD 0
1437 DD PATM_INTERRUPTFLAG
1438 DD 0
1439 DD PATM_INTERRUPTFLAG
1440 DD 0
1441 DD PATM_INTERRUPTFLAG
1442 DD 0
1443 DD PATM_FIXUP
1444 DD PATMIretTable - PATMIretStart
1445 DD PATM_IRET_FUNCTION
1446 DD 0
1447 DD PATM_VMFLAGS
1448 DD 0
1449 DD PATM_VMFLAGS
1450 DD 0
1451 DD PATM_VMFLAGS
1452 DD 0
1453 DD PATM_TEMP_EAX
1454 DD 0
1455 DD PATM_TEMP_ECX
1456 DD 0
1457 DD PATM_TEMP_RESTORE_FLAGS
1458 DD 0
1459 DD PATM_PENDINGACTION
1460 DD 0
1461 DD 0ffffffffh
1462SECTION .text
1463
1464
1465;
1466; global function for implementing 'iret' to code with IF cleared
1467;
1468; Caller is responsible for right stack layout
1469; + 16 original return address
1470; + 12 eflags
1471; + 8 eax
1472; + 4 Jump table address
1473;( + 0 return address )
1474;
1475; @note assumes PATM_INTERRUPTFLAG is zero
1476; @note assumes it can trash eax and eflags
1477;
1478; @returns eax=0 on failure
1479; otherwise return address in eax
1480;
1481; @note NEVER change this without bumping the SSM version
1482align 32
1483BEGINPROC PATMIretFunction
1484PATMIretFunction_Start:
1485 push ecx
1486 push edx
1487 push edi
1488
1489 ; Event order:
1490 ; 1) Check if the return patch address can be found in the lookup table
1491 ; 2) Query return patch address from the hypervisor
1492
1493 ; 1) Check if the return patch address can be found in the lookup table
1494 mov edx, dword [esp+12+16] ; pushed target address
1495
1496 xor eax, eax ; default result -> nothing found
1497 mov edi, dword [esp+12+4] ; jump table
1498 mov ecx, [ss:edi + PATCHJUMPTABLE.cAddresses]
1499 cmp ecx, 0
1500 je near PATMIretFunction_AskHypervisor
1501
1502PATMIretFunction_SearchStart:
1503 cmp [ss:edi + PATCHJUMPTABLE.Slot_pInstrGC + eax*8], edx ; edx = GC address to search for
1504 je near PATMIretFunction_SearchHit
1505 inc eax
1506 cmp eax, ecx
1507 jl near PATMIretFunction_SearchStart
1508
1509PATMIretFunction_AskHypervisor:
1510 ; 2) Query return patch address from the hypervisor
1511 ; @todo private ugly interface, since we have nothing generic at the moment
1512 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOOKUP_ADDRESS
1513 mov eax, PATM_ACTION_LOOKUP_ADDRESS
1514 mov ecx, PATM_ACTION_MAGIC
1515 mov edi, dword [esp+12+4] ; jump table address
1516 mov edx, dword [esp+12+16] ; original return address
1517 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1518 jmp near PATMIretFunction_SearchEnd
1519
1520PATMIretFunction_SearchHit:
1521 mov eax, [ss:edi + PATCHJUMPTABLE.Slot_pRelPatchGC + eax*8] ; found a match!
1522 ;@note can be zero, so the next check is required!!
1523
1524PATMIretFunction_SearchEnd:
1525 cmp eax, 0
1526 jz PATMIretFunction_Failure
1527
1528 add eax, PATM_PATCHBASE
1529
1530 pop edi
1531 pop edx
1532 pop ecx
1533 ret
1534
1535PATMIretFunction_Failure:
1536 ;signal error
1537 xor eax, eax
1538 pop edi
1539 pop edx
1540 pop ecx
1541 ret
1542
1543PATMIretFunction_End:
1544ENDPROC PATMIretFunction
1545
1546SECTION .data
1547GLOBALNAME PATMIretFunctionRecord
1548 RTCCPTR_DEF PATMIretFunction_Start
1549 DD 0
1550 DD 0
1551 DD 0
1552 DD PATMIretFunction_End - PATMIretFunction_Start
1553 DD 2
1554 DD PATM_PENDINGACTION
1555 DD 0
1556 DD PATM_PATCHBASE
1557 DD 0
1558 DD 0ffffffffh
1559SECTION .text
1560
1561
1562align 32 ; yasm / nasm diff - remove me!
1563BEGINPROC PATMCpuidReplacement
1564PATMCpuidStart:
1565 mov dword [ss:PATM_INTERRUPTFLAG], 0
1566 pushf
1567
1568 cmp eax, PATM_CPUID_STD_MAX
1569 jb cpuid_std
1570 cmp eax, 0x80000000
1571 jb cpuid_def
1572 cmp eax, PATM_CPUID_EXT_MAX
1573 jb cpuid_ext
1574 cmp eax, 0xc0000000
1575 jb cpuid_def
1576 cmp eax, PATM_CPUID_CENTAUR_MAX
1577 jb cpuid_centaur
1578
1579 ; Dirty assumptions in patmCorrectFixup about the pointer fixup order!!!!
1580cpuid_def:
1581 mov eax, PATM_CPUID_DEF_PTR
1582 jmp cpuid_fetch
1583
1584cpuid_std:
1585 mov edx, PATM_CPUID_STD_PTR
1586 jmp cpuid_calc
1587
1588cpuid_ext:
1589 and eax, 0ffh ; strictly speaking not necessary.
1590 mov edx, PATM_CPUID_EXT_PTR
1591 jmp cpuid_calc
1592
1593cpuid_centaur:
1594 and eax, 0ffh ; strictly speaking not necessary.
1595 mov edx, PATM_CPUID_CENTAUR_PTR
1596
1597cpuid_calc:
1598 lea eax, [ss:eax * 4] ; 4 entries...
1599 lea eax, [ss:eax * 4] ; 4 bytes each
1600 add eax, edx
1601
1602cpuid_fetch:
1603 mov edx, [ss:eax + 12] ; CPUMCPUID layout assumptions!
1604 mov ecx, [ss:eax + 8]
1605 mov ebx, [ss:eax + 4]
1606 mov eax, [ss:eax]
1607
1608 popf
1609 mov dword [ss:PATM_INTERRUPTFLAG], 1
1610
1611PATMCpuidEnd:
1612ENDPROC PATMCpuidReplacement
1613
1614SECTION .data
1615; Patch record for 'cpuid'
1616GLOBALNAME PATMCpuidRecord
1617 RTCCPTR_DEF PATMCpuidStart
1618 DD 0
1619 DD 0
1620 DD 0
1621 DD PATMCpuidEnd- PATMCpuidStart
1622 DD 9
1623 DD PATM_INTERRUPTFLAG
1624 DD 0
1625 DD PATM_CPUID_STD_MAX
1626 DD 0
1627 DD PATM_CPUID_EXT_MAX
1628 DD 0
1629 DD PATM_CPUID_CENTAUR_MAX
1630 DD 0
1631 DD PATM_CPUID_DEF_PTR
1632 DD 0
1633 DD PATM_CPUID_STD_PTR
1634 DD 0
1635 DD PATM_CPUID_EXT_PTR
1636 DD 0
1637 DD PATM_CPUID_CENTAUR_PTR
1638 DD 0
1639 DD PATM_INTERRUPTFLAG
1640 DD 0
1641 DD 0ffffffffh
1642SECTION .text
1643
1644
1645BEGINPROC PATMJEcxReplacement
1646PATMJEcxStart:
1647 mov dword [ss:PATM_INTERRUPTFLAG], 0
1648 pushfd
1649PATMJEcxSizeOverride:
1650 DB 0x90 ; nop
1651 cmp ecx, dword 0 ; yasm / nasm dword
1652 jnz PATMJEcxContinue
1653
1654 popfd
1655 mov dword [ss:PATM_INTERRUPTFLAG], 1
1656 DB 0xE9
1657PATMJEcxJump:
1658 DD PATM_JUMPDELTA
1659
1660PATMJEcxContinue:
1661 popfd
1662 mov dword [ss:PATM_INTERRUPTFLAG], 1
1663PATMJEcxEnd:
1664ENDPROC PATMJEcxReplacement
1665
1666SECTION .data
1667; Patch record for 'JEcx'
1668GLOBALNAME PATMJEcxRecord
1669 RTCCPTR_DEF PATMJEcxStart
1670 DD 0
1671 DD PATMJEcxJump - PATMJEcxStart
1672 DD PATMJEcxSizeOverride - PATMJEcxStart
1673 DD PATMJEcxEnd- PATMJEcxStart
1674 DD 3
1675 DD PATM_INTERRUPTFLAG
1676 DD 0
1677 DD PATM_INTERRUPTFLAG
1678 DD 0
1679 DD PATM_INTERRUPTFLAG
1680 DD 0
1681 DD 0ffffffffh
1682SECTION .text
1683
1684align 32; yasm / nasm diffing. remove me!
1685BEGINPROC PATMLoopReplacement
1686PATMLoopStart:
1687 mov dword [ss:PATM_INTERRUPTFLAG], 0
1688 pushfd
1689PATMLoopSizeOverride:
1690 DB 0x90 ; nop
1691 dec ecx
1692 jz PATMLoopContinue
1693
1694 popfd
1695 mov dword [ss:PATM_INTERRUPTFLAG], 1
1696 DB 0xE9
1697PATMLoopJump:
1698 DD PATM_JUMPDELTA
1699
1700PATMLoopContinue:
1701 popfd
1702 mov dword [ss:PATM_INTERRUPTFLAG], 1
1703PATMLoopEnd:
1704ENDPROC PATMLoopReplacement
1705
1706SECTION .data
1707; Patch record for 'Loop'
1708GLOBALNAME PATMLoopRecord
1709 RTCCPTR_DEF PATMLoopStart
1710 DD 0
1711 DD PATMLoopJump - PATMLoopStart
1712 DD PATMLoopSizeOverride - PATMLoopStart
1713 DD PATMLoopEnd- PATMLoopStart
1714 DD 3
1715 DD PATM_INTERRUPTFLAG
1716 DD 0
1717 DD PATM_INTERRUPTFLAG
1718 DD 0
1719 DD PATM_INTERRUPTFLAG
1720 DD 0
1721 DD 0ffffffffh
1722SECTION .text
1723
1724BEGINPROC PATMLoopZReplacement
1725PATMLoopZStart:
1726 ; jump if ZF=1 AND (E)CX != 0
1727
1728 mov dword [ss:PATM_INTERRUPTFLAG], 0
1729 jnz PATMLoopZEnd
1730 pushfd
1731PATMLoopZSizeOverride:
1732 DB 0x90 ; nop
1733 dec ecx
1734 jz PATMLoopZContinue
1735
1736 popfd
1737 mov dword [ss:PATM_INTERRUPTFLAG], 1
1738 DB 0xE9
1739PATMLoopZJump:
1740 DD PATM_JUMPDELTA
1741
1742PATMLoopZContinue:
1743 popfd
1744 mov dword [ss:PATM_INTERRUPTFLAG], 1
1745PATMLoopZEnd:
1746ENDPROC PATMLoopZReplacement
1747
1748SECTION .data
1749; Patch record for 'Loopz'
1750GLOBALNAME PATMLoopZRecord
1751 RTCCPTR_DEF PATMLoopZStart
1752 DD 0
1753 DD PATMLoopZJump - PATMLoopZStart
1754 DD PATMLoopZSizeOverride - PATMLoopZStart
1755 DD PATMLoopZEnd- PATMLoopZStart
1756 DD 3
1757 DD PATM_INTERRUPTFLAG
1758 DD 0
1759 DD PATM_INTERRUPTFLAG
1760 DD 0
1761 DD PATM_INTERRUPTFLAG
1762 DD 0
1763 DD 0ffffffffh
1764SECTION .text
1765
1766
1767BEGINPROC PATMLoopNZReplacement
1768PATMLoopNZStart:
1769 ; jump if ZF=0 AND (E)CX != 0
1770
1771 mov dword [ss:PATM_INTERRUPTFLAG], 0
1772 jz PATMLoopNZEnd
1773 pushfd
1774PATMLoopNZSizeOverride:
1775 DB 0x90 ; nop
1776 dec ecx
1777 jz PATMLoopNZContinue
1778
1779 popfd
1780 mov dword [ss:PATM_INTERRUPTFLAG], 1
1781 DB 0xE9
1782PATMLoopNZJump:
1783 DD PATM_JUMPDELTA
1784
1785PATMLoopNZContinue:
1786 popfd
1787 mov dword [ss:PATM_INTERRUPTFLAG], 1
1788PATMLoopNZEnd:
1789ENDPROC PATMLoopNZReplacement
1790
1791SECTION .data
1792; Patch record for 'LoopNZ'
1793GLOBALNAME PATMLoopNZRecord
1794 RTCCPTR_DEF PATMLoopNZStart
1795 DD 0
1796 DD PATMLoopNZJump - PATMLoopNZStart
1797 DD PATMLoopNZSizeOverride - PATMLoopNZStart
1798 DD PATMLoopNZEnd- PATMLoopNZStart
1799 DD 3
1800 DD PATM_INTERRUPTFLAG
1801 DD 0
1802 DD PATM_INTERRUPTFLAG
1803 DD 0
1804 DD PATM_INTERRUPTFLAG
1805 DD 0
1806 DD 0ffffffffh
1807SECTION .text
1808
1809align 32
1810; Global patch function for indirect calls
1811; Caller is responsible for clearing PATM_INTERRUPTFLAG and doing:
1812; + 20 push [pTargetGC]
1813; + 16 pushfd
1814; + 12 push [JumpTableAddress]
1815; + 8 push [PATMRelReturnAddress]
1816; + 4 push [GuestReturnAddress]
1817;( + 0 return address )
1818;
1819; @note NEVER change this without bumping the SSM version
1820BEGINPROC PATMLookupAndCall
1821PATMLookupAndCallStart:
1822 push eax
1823 push edx
1824 push edi
1825 push ecx
1826
1827 mov eax, dword [esp+16+4] ; guest return address
1828 mov dword [ss:PATM_CALL_RETURN_ADDR], eax ; temporary storage
1829
1830 mov edx, dword [esp+16+20] ; pushed target address
1831
1832 xor eax, eax ; default result -> nothing found
1833 mov edi, dword [esp+16+12] ; jump table
1834 mov ecx, [ss:edi + PATCHJUMPTABLE.cAddresses]
1835 cmp ecx, 0
1836 je near PATMLookupAndCall_QueryPATM
1837
1838PATMLookupAndCall_SearchStart:
1839 cmp [ss:edi + PATCHJUMPTABLE.Slot_pInstrGC + eax*8], edx ; edx = GC address to search for
1840 je near PATMLookupAndCall_SearchHit
1841 inc eax
1842 cmp eax, ecx
1843 jl near PATMLookupAndCall_SearchStart
1844
1845PATMLookupAndCall_QueryPATM:
1846 ; nothing found -> let our trap handler try to find it
1847 ; @todo private ugly interface, since we have nothing generic at the moment
1848 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOOKUP_ADDRESS
1849 mov eax, PATM_ACTION_LOOKUP_ADDRESS
1850 mov ecx, PATM_ACTION_MAGIC
1851 ; edx = GC address to find
1852 ; edi = jump table address
1853 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1854
1855 jmp near PATMLookupAndCall_SearchEnd
1856
1857PATMLookupAndCall_Failure:
1858 ; return to caller; it must raise an error, due to patch to guest address translation (remember that there's only one copy of this code block).
1859 pop ecx
1860 pop edi
1861 pop edx
1862 pop eax
1863 ret
1864
1865PATMLookupAndCall_SearchHit:
1866 mov eax, [ss:edi + PATCHJUMPTABLE.Slot_pRelPatchGC + eax*8] ; found a match!
1867
1868 ;@note can be zero, so the next check is required!!
1869
1870PATMLookupAndCall_SearchEnd:
1871 cmp eax, 0
1872 je near PATMLookupAndCall_Failure
1873
1874 mov ecx, eax ; ECX = target address (relative!)
1875 add ecx, PATM_PATCHBASE ; Make it absolute
1876
1877 mov edx, dword PATM_STACKPTR
1878 cmp dword [ss:edx], PATM_STACK_SIZE
1879 ja near PATMLookupAndCall_Failure ; should never happen actually!!!
1880 cmp dword [ss:edx], 0
1881 je near PATMLookupAndCall_Failure ; no more room
1882
1883 ; save the patch return address on our private stack
1884 sub dword [ss:edx], 4 ; sizeof(RTGCPTR)
1885 mov eax, dword PATM_STACKBASE
1886 add eax, dword [ss:edx] ; stack base + stack position
1887 mov edi, dword [esp+16+8] ; PATM return address
1888 mov dword [ss:eax], edi ; relative address of patch return (instruction following this block)
1889
1890 ; save the original return address as well (checked by ret to make sure the guest hasn't messed around with the stack)
1891 mov edi, dword PATM_STACKBASE_GUEST
1892 add edi, dword [ss:edx] ; stack base (guest) + stack position
1893 mov eax, dword [esp+16+4] ; guest return address
1894 mov dword [ss:edi], eax
1895
1896 mov dword [ss:PATM_CALL_PATCH_TARGET_ADDR], ecx ; temporarily store the target address
1897 pop ecx
1898 pop edi
1899 pop edx
1900 pop eax
1901 add esp, 24 ; parameters + return address pushed by caller (changes the flags, but that shouldn't matter)
1902
1903%ifdef PATM_LOG_PATCHINSTR
1904 push eax
1905 push ecx
1906 push edx
1907 lea edx, [esp + 12 - 4] ; stack address to store return address
1908 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOG_CALL
1909 mov eax, PATM_ACTION_LOG_CALL
1910 mov ecx, PATM_ACTION_MAGIC
1911 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
1912 pop edx
1913 pop ecx
1914 pop eax
1915%endif
1916
1917 push dword [ss:PATM_CALL_RETURN_ADDR] ; push original guest return address
1918
1919 ; the called function will set PATM_INTERRUPTFLAG (!!)
1920 jmp dword [ss:PATM_CALL_PATCH_TARGET_ADDR]
1921
1922PATMLookupAndCallEnd:
1923; returning here -> do not add code here or after the jmp!!!!!
1924ENDPROC PATMLookupAndCall
1925
1926SECTION .data
1927; Patch record for indirect calls and jumps
1928GLOBALNAME PATMLookupAndCallRecord
1929 RTCCPTR_DEF PATMLookupAndCallStart
1930 DD 0
1931 DD 0
1932 DD 0
1933 DD PATMLookupAndCallEnd - PATMLookupAndCallStart
1934%ifdef PATM_LOG_PATCHINSTR
1935 DD 10
1936%else
1937 DD 9
1938%endif
1939 DD PATM_CALL_RETURN_ADDR
1940 DD 0
1941 DD PATM_PENDINGACTION
1942 DD 0
1943 DD PATM_PATCHBASE
1944 DD 0
1945 DD PATM_STACKPTR
1946 DD 0
1947 DD PATM_STACKBASE
1948 DD 0
1949 DD PATM_STACKBASE_GUEST
1950 DD 0
1951 DD PATM_CALL_PATCH_TARGET_ADDR
1952 DD 0
1953%ifdef PATM_LOG_PATCHINSTR
1954 DD PATM_PENDINGACTION
1955 DD 0
1956%endif
1957 DD PATM_CALL_RETURN_ADDR
1958 DD 0
1959 DD PATM_CALL_PATCH_TARGET_ADDR
1960 DD 0
1961 DD 0ffffffffh
1962SECTION .text
1963
1964
1965align 32
1966; Global patch function for indirect jumps
1967; Caller is responsible for clearing PATM_INTERRUPTFLAG and doing:
1968; + 8 push [pTargetGC]
1969; + 4 push [JumpTableAddress]
1970;( + 0 return address )
1971; And saving eflags in PATM_TEMP_EFLAGS
1972;
1973; @note NEVER change this without bumping the SSM version
1974BEGINPROC PATMLookupAndJump
1975PATMLookupAndJumpStart:
1976 push eax
1977 push edx
1978 push edi
1979 push ecx
1980
1981 mov edx, dword [esp+16+8] ; pushed target address
1982
1983 xor eax, eax ; default result -> nothing found
1984 mov edi, dword [esp+16+4] ; jump table
1985 mov ecx, [ss:edi + PATCHJUMPTABLE.cAddresses]
1986 cmp ecx, 0
1987 je near PATMLookupAndJump_QueryPATM
1988
1989PATMLookupAndJump_SearchStart:
1990 cmp [ss:edi + PATCHJUMPTABLE.Slot_pInstrGC + eax*8], edx ; edx = GC address to search for
1991 je near PATMLookupAndJump_SearchHit
1992 inc eax
1993 cmp eax, ecx
1994 jl near PATMLookupAndJump_SearchStart
1995
1996PATMLookupAndJump_QueryPATM:
1997 ; nothing found -> let our trap handler try to find it
1998 ; @todo private ugly interface, since we have nothing generic at the moment
1999 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOOKUP_ADDRESS
2000 mov eax, PATM_ACTION_LOOKUP_ADDRESS
2001 mov ecx, PATM_ACTION_MAGIC
2002 ; edx = GC address to find
2003 ; edi = jump table address
2004 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
2005
2006 jmp near PATMLookupAndJump_SearchEnd
2007
2008PATMLookupAndJump_Failure:
2009 ; return to caller; it must raise an error, due to patch to guest address translation (remember that there's only one copy of this code block).
2010 pop ecx
2011 pop edi
2012 pop edx
2013 pop eax
2014 ret
2015
2016PATMLookupAndJump_SearchHit:
2017 mov eax, [ss:edi + PATCHJUMPTABLE.Slot_pRelPatchGC + eax*8] ; found a match!
2018
2019 ;@note can be zero, so the next check is required!!
2020
2021PATMLookupAndJump_SearchEnd:
2022 cmp eax, 0
2023 je near PATMLookupAndJump_Failure
2024
2025 mov ecx, eax ; ECX = target address (relative!)
2026 add ecx, PATM_PATCHBASE ; Make it absolute
2027
2028 ; save jump patch target
2029 mov dword [ss:PATM_TEMP_EAX], ecx
2030 pop ecx
2031 pop edi
2032 pop edx
2033 pop eax
2034 add esp, 12 ; parameters + return address pushed by caller
2035 ; restore flags (just to be sure)
2036 push dword [ss:PATM_TEMP_EFLAGS]
2037 popfd
2038
2039 ; the jump destination will set PATM_INTERRUPTFLAG (!!)
2040 jmp dword [ss:PATM_TEMP_EAX] ; call duplicated patch destination address
2041
2042PATMLookupAndJumpEnd:
2043ENDPROC PATMLookupAndJump
2044
2045SECTION .data
2046; Patch record for indirect calls and jumps
2047GLOBALNAME PATMLookupAndJumpRecord
2048 RTCCPTR_DEF PATMLookupAndJumpStart
2049 DD 0
2050 DD 0
2051 DD 0
2052 DD PATMLookupAndJumpEnd - PATMLookupAndJumpStart
2053 DD 5
2054 DD PATM_PENDINGACTION
2055 DD 0
2056 DD PATM_PATCHBASE
2057 DD 0
2058 DD PATM_TEMP_EAX
2059 DD 0
2060 DD PATM_TEMP_EFLAGS
2061 DD 0
2062 DD PATM_TEMP_EAX
2063 DD 0
2064 DD 0ffffffffh
2065SECTION .text
2066
2067
2068
2069
2070align 32
2071; Patch function for static calls
2072; @note static calls have only one lookup slot!
2073; Caller is responsible for clearing PATM_INTERRUPTFLAG and adding:
2074; push [pTargetGC]
2075;
2076BEGINPROC PATMCall
2077PATMCallStart:
2078 pushfd
2079 push PATM_FIXUP ; fixup for jump table below
2080 push PATM_PATCHNEXTBLOCK
2081 push PATM_RETURNADDR
2082 DB 0E8h ; call
2083 DD PATM_LOOKUP_AND_CALL_FUNCTION
2084 ; we only return in case of a failure
2085 add esp, 12 ; pushed address of jump table
2086 popfd
2087 add esp, 4 ; pushed by caller (changes the flags, but that shouldn't matter (@todo))
2088 mov dword [ss:PATM_INTERRUPTFLAG], 1
2089 PATM_INT3
2090%ifdef DEBUG
2091 ; for disassembly
2092 jmp PATMCallEnd
2093%endif
2094
2095align 4
2096PATMCallTable:
2097 DW 1 ; nrSlots
2098 DW 0 ; ulInsertPos
2099 DD 0 ; cAddresses
2100 TIMES PATCHDIRECTJUMPTABLE_SIZE DB 0 ; only one lookup slot
2101
2102PATMCallEnd:
2103; returning here -> do not add code here or after the jmp!!!!!
2104ENDPROC PATMCall
2105
2106SECTION .data
2107; Patch record for direct calls
2108GLOBALNAME PATMCallRecord
2109 RTCCPTR_DEF PATMCallStart
2110 DD 0
2111 DD 0
2112 DD 0
2113 DD PATMCallEnd - PATMCallStart
2114 DD 5
2115 DD PATM_FIXUP
2116 DD PATMCallTable - PATMCallStart
2117 DD PATM_PATCHNEXTBLOCK
2118 DD 0
2119 DD PATM_RETURNADDR
2120 DD 0
2121 DD PATM_LOOKUP_AND_CALL_FUNCTION
2122 DD 0
2123 DD PATM_INTERRUPTFLAG
2124 DD 0
2125 DD 0ffffffffh
2126SECTION .text
2127
2128
2129align 32
2130; Patch function for indirect calls
2131; Caller is responsible for clearing PATM_INTERRUPTFLAG and adding:
2132; push [pTargetGC]
2133;
2134BEGINPROC PATMCallIndirect
2135PATMCallIndirectStart:
2136 pushfd
2137 push PATM_FIXUP ; fixup for jump table below
2138 push PATM_PATCHNEXTBLOCK
2139 push PATM_RETURNADDR
2140 DB 0E8h ; call
2141 DD PATM_LOOKUP_AND_CALL_FUNCTION
2142 ; we only return in case of a failure
2143 add esp, 12 ; pushed address of jump table
2144 popfd
2145 add esp, 4 ; pushed by caller (changes the flags, but that shouldn't matter (@todo))
2146 mov dword [ss:PATM_INTERRUPTFLAG], 1
2147 PATM_INT3
2148%ifdef DEBUG
2149 ; for disassembly
2150 jmp PATMCallIndirectEnd
2151%endif
2152
2153align 4
2154PATMCallIndirectTable:
2155 DW PATM_MAX_JUMPTABLE_ENTRIES ; nrSlots
2156 DW 0 ; ulInsertPos
2157 DD 0 ; cAddresses
2158 TIMES PATCHJUMPTABLE_SIZE DB 0 ; lookup slots
2159
2160PATMCallIndirectEnd:
2161; returning here -> do not add code here or after the jmp!!!!!
2162ENDPROC PATMCallIndirect
2163
2164SECTION .data
2165; Patch record for indirect calls
2166GLOBALNAME PATMCallIndirectRecord
2167 RTCCPTR_DEF PATMCallIndirectStart
2168 DD 0
2169 DD 0
2170 DD 0
2171 DD PATMCallIndirectEnd - PATMCallIndirectStart
2172 DD 5
2173 DD PATM_FIXUP
2174 DD PATMCallIndirectTable - PATMCallIndirectStart
2175 DD PATM_PATCHNEXTBLOCK
2176 DD 0
2177 DD PATM_RETURNADDR
2178 DD 0
2179 DD PATM_LOOKUP_AND_CALL_FUNCTION
2180 DD 0
2181 DD PATM_INTERRUPTFLAG
2182 DD 0
2183 DD 0ffffffffh
2184SECTION .text
2185
2186
2187align 32
2188; Patch function for indirect jumps
2189; Caller is responsible for clearing PATM_INTERRUPTFLAG and adding:
2190; push [pTargetGC]
2191;
2192BEGINPROC PATMJumpIndirect
2193PATMJumpIndirectStart:
2194 ; save flags (just to be sure)
2195 pushfd
2196 pop dword [ss:PATM_TEMP_EFLAGS]
2197
2198 push PATM_FIXUP ; fixup for jump table below
2199 DB 0E8h ; call
2200 DD PATM_LOOKUP_AND_JUMP_FUNCTION
2201 ; we only return in case of a failure
2202 add esp, 8 ; pushed address of jump table + pushed target address
2203
2204 ; restore flags (just to be sure)
2205 push dword [ss:PATM_TEMP_EFLAGS]
2206 popfd
2207
2208 mov dword [ss:PATM_INTERRUPTFLAG], 1
2209 PATM_INT3
2210
2211%ifdef DEBUG
2212 ; for disassembly
2213 jmp PATMJumpIndirectEnd
2214%endif
2215
2216align 4
2217PATMJumpIndirectTable:
2218 DW PATM_MAX_JUMPTABLE_ENTRIES ; nrSlots
2219 DW 0 ; ulInsertPos
2220 DD 0 ; cAddresses
2221 TIMES PATCHJUMPTABLE_SIZE DB 0 ; lookup slots
2222
2223PATMJumpIndirectEnd:
2224; returning here -> do not add code here or after the jmp!!!!!
2225ENDPROC PATMJumpIndirect
2226
2227SECTION .data
2228; Patch record for indirect jumps
2229GLOBALNAME PATMJumpIndirectRecord
2230 RTCCPTR_DEF PATMJumpIndirectStart
2231 DD 0
2232 DD 0
2233 DD 0
2234 DD PATMJumpIndirectEnd - PATMJumpIndirectStart
2235 DD 5
2236 DD PATM_TEMP_EFLAGS
2237 DD 0
2238 DD PATM_FIXUP
2239 DD PATMJumpIndirectTable - PATMJumpIndirectStart
2240 DD PATM_LOOKUP_AND_JUMP_FUNCTION
2241 DD 0
2242 DD PATM_TEMP_EFLAGS
2243 DD 0
2244 DD PATM_INTERRUPTFLAG
2245 DD 0
2246 DD 0ffffffffh
2247SECTION .text
2248
2249;
2250; return from duplicated function
2251;
2252align 32
2253BEGINPROC PATMRet
2254PATMRet_Start:
2255 ; probe stack here as we can't recover from page faults later on
2256 not dword [esp-32]
2257 not dword [esp-32]
2258 mov dword [ss:PATM_INTERRUPTFLAG], 0
2259 pushfd
2260 push eax
2261 push PATM_FIXUP
2262 DB 0E8h ; call
2263 DD PATM_RETURN_FUNCTION
2264 add esp, 4 ; pushed address of jump table
2265
2266 cmp eax, 0
2267 jne near PATMRet_Success
2268
2269 pop eax
2270 popfd
2271 mov dword [ss:PATM_INTERRUPTFLAG], 1
2272 PATM_INT3
2273
2274%ifdef DEBUG
2275 ; for disassembly
2276 jmp PATMRet_Success
2277%endif
2278align 4
2279PATMRetTable:
2280 DW PATM_MAX_JUMPTABLE_ENTRIES ; nrSlots
2281 DW 0 ; ulInsertPos
2282 DD 0 ; cAddresses
2283 TIMES PATCHJUMPTABLE_SIZE DB 0 ; lookup slots
2284
2285PATMRet_Success:
2286 mov dword [esp+8], eax ; overwrite the saved return address
2287 pop eax
2288 popf
2289 ; caller will duplicate the ret or ret n instruction
2290 ; the patched call will set PATM_INTERRUPTFLAG after the return!
2291PATMRet_End:
2292ENDPROC PATMRet
2293
2294SECTION .data
2295GLOBALNAME PATMRetRecord
2296 RTCCPTR_DEF PATMRet_Start
2297 DD 0
2298 DD 0
2299 DD 0
2300 DD PATMRet_End - PATMRet_Start
2301 DD 4
2302 DD PATM_INTERRUPTFLAG
2303 DD 0
2304 DD PATM_FIXUP
2305 DD PATMRetTable - PATMRet_Start
2306 DD PATM_RETURN_FUNCTION
2307 DD 0
2308 DD PATM_INTERRUPTFLAG
2309 DD 0
2310 DD 0ffffffffh
2311SECTION .text
2312
2313;
2314; global function for implementing 'retn'
2315;
2316; Caller is responsible for right stack layout
2317; + 16 original return address
2318; + 12 eflags
2319; + 8 eax
2320; + 4 Jump table address
2321;( + 0 return address )
2322;
2323; @note assumes PATM_INTERRUPTFLAG is zero
2324; @note assumes it can trash eax and eflags
2325;
2326; @returns eax=0 on failure
2327; otherwise return address in eax
2328;
2329; @note NEVER change this without bumping the SSM version
2330align 32
2331BEGINPROC PATMRetFunction
2332PATMRetFunction_Start:
2333 push ecx
2334 push edx
2335 push edi
2336
2337 ; Event order:
2338 ; (@todo figure out which path is taken most often (1 or 2))
2339 ; 1) Check if the return patch address was pushed onto the PATM stack
2340 ; 2) Check if the return patch address can be found in the lookup table
2341 ; 3) Query return patch address from the hypervisor
2342
2343
2344 ; 1) Check if the return patch address was pushed on the PATM stack
2345 cmp dword [ss:PATM_STACKPTR], PATM_STACK_SIZE
2346 jae near PATMRetFunction_FindReturnAddress
2347
2348 mov edx, dword PATM_STACKPTR
2349
2350 ; check if the return address is what we expect it to be
2351 mov eax, dword PATM_STACKBASE_GUEST
2352 add eax, dword [ss:edx] ; stack base + stack position
2353 mov eax, dword [ss:eax] ; original return address
2354 cmp eax, dword [esp+12+16] ; pushed return address
2355
2356 ; the return address was changed -> let our trap handler try to find it
2357 ; (can happen when the guest messes with the stack (seen it) or when we didn't call this function ourselves)
2358 jne near PATMRetFunction_FindReturnAddress
2359
2360 ; found it, convert relative to absolute patch address and return the result to the caller
2361 mov eax, dword PATM_STACKBASE
2362 add eax, dword [ss:edx] ; stack base + stack position
2363 mov eax, dword [ss:eax] ; relative patm return address
2364 add eax, PATM_PATCHBASE
2365
2366%ifdef PATM_LOG_PATCHINSTR
2367 push eax
2368 push ebx
2369 push ecx
2370 push edx
2371 mov edx, eax ; return address
2372 lea ebx, [esp+16+12+16] ; stack address containing the return address
2373 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOG_RET
2374 mov eax, PATM_ACTION_LOG_RET
2375 mov ecx, PATM_ACTION_MAGIC
2376 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
2377 pop edx
2378 pop ecx
2379 pop ebx
2380 pop eax
2381%endif
2382
2383 add dword [ss:edx], 4 ; pop return address from the PATM stack (sizeof(RTGCPTR); @note hardcoded assumption!)
2384
2385 pop edi
2386 pop edx
2387 pop ecx
2388 ret
2389
2390PATMRetFunction_FindReturnAddress:
2391 ; 2) Check if the return patch address can be found in the lookup table
2392 mov edx, dword [esp+12+16] ; pushed target address
2393
2394 xor eax, eax ; default result -> nothing found
2395 mov edi, dword [esp+12+4] ; jump table
2396 mov ecx, [ss:edi + PATCHJUMPTABLE.cAddresses]
2397 cmp ecx, 0
2398 je near PATMRetFunction_AskHypervisor
2399
2400PATMRetFunction_SearchStart:
2401 cmp [ss:edi + PATCHJUMPTABLE.Slot_pInstrGC + eax*8], edx ; edx = GC address to search for
2402 je near PATMRetFunction_SearchHit
2403 inc eax
2404 cmp eax, ecx
2405 jl near PATMRetFunction_SearchStart
2406
2407PATMRetFunction_AskHypervisor:
2408 ; 3) Query return patch address from the hypervisor
2409 ; @todo private ugly interface, since we have nothing generic at the moment
2410 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOOKUP_ADDRESS
2411 mov eax, PATM_ACTION_LOOKUP_ADDRESS
2412 mov ecx, PATM_ACTION_MAGIC
2413 mov edi, dword [esp+12+4] ; jump table address
2414 mov edx, dword [esp+12+16] ; original return address
2415 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
2416 jmp near PATMRetFunction_SearchEnd
2417
2418PATMRetFunction_SearchHit:
2419 mov eax, [ss:edi + PATCHJUMPTABLE.Slot_pRelPatchGC + eax*8] ; found a match!
2420 ;@note can be zero, so the next check is required!!
2421
2422PATMRetFunction_SearchEnd:
2423 cmp eax, 0
2424 jz PATMRetFunction_Failure
2425
2426 add eax, PATM_PATCHBASE
2427
2428%ifdef PATM_LOG_PATCHINSTR
2429 push eax
2430 push ebx
2431 push ecx
2432 push edx
2433 mov edx, eax ; return address
2434 lea ebx, [esp+16+12+16] ; stack address containing the return address
2435 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOG_RET
2436 mov eax, PATM_ACTION_LOG_RET
2437 mov ecx, PATM_ACTION_MAGIC
2438 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
2439 pop edx
2440 pop ecx
2441 pop ebx
2442 pop eax
2443%endif
2444
2445 pop edi
2446 pop edx
2447 pop ecx
2448 ret
2449
2450PATMRetFunction_Failure:
2451 ;signal error
2452 xor eax, eax
2453 pop edi
2454 pop edx
2455 pop ecx
2456 ret
2457
2458PATMRetFunction_End:
2459ENDPROC PATMRetFunction
2460
2461SECTION .data
2462GLOBALNAME PATMRetFunctionRecord
2463 RTCCPTR_DEF PATMRetFunction_Start
2464 DD 0
2465 DD 0
2466 DD 0
2467 DD PATMRetFunction_End - PATMRetFunction_Start
2468%ifdef PATM_LOG_PATCHINSTR
2469 DD 9
2470%else
2471 DD 7
2472%endif
2473 DD PATM_STACKPTR
2474 DD 0
2475 DD PATM_STACKPTR
2476 DD 0
2477 DD PATM_STACKBASE_GUEST
2478 DD 0
2479 DD PATM_STACKBASE
2480 DD 0
2481 DD PATM_PATCHBASE
2482 DD 0
2483%ifdef PATM_LOG_PATCHINSTR
2484 DD PATM_PENDINGACTION
2485 DD 0
2486%endif
2487 DD PATM_PENDINGACTION
2488 DD 0
2489 DD PATM_PATCHBASE
2490 DD 0
2491%ifdef PATM_LOG_PATCHINSTR
2492 DD PATM_PENDINGACTION
2493 DD 0
2494%endif
2495 DD 0ffffffffh
2496SECTION .text
2497
2498
2499;
2500; Jump to original instruction if IF=1
2501;
2502BEGINPROC PATMCheckIF
2503PATMCheckIF_Start:
2504 mov dword [ss:PATM_INTERRUPTFLAG], 0
2505 pushf
2506 test dword [ss:PATM_VMFLAGS], X86_EFL_IF
2507 jnz PATMCheckIF_Safe
2508 nop
2509
2510 ; IF=0 -> unsafe, so we must call the duplicated function (which we don't do here)
2511 popf
2512 mov dword [ss:PATM_INTERRUPTFLAG], 1
2513 jmp PATMCheckIF_End
2514
2515PATMCheckIF_Safe:
2516 ; invalidate the PATM stack as we'll jump back to guest code
2517 mov dword [ss:PATM_STACKPTR], PATM_STACK_SIZE
2518
2519%ifdef PATM_LOG_PATCHINSTR
2520 push eax
2521 push ecx
2522 lock or dword [ss:PATM_PENDINGACTION], PATM_ACTION_LOG_IF1
2523 mov eax, PATM_ACTION_LOG_IF1
2524 mov ecx, PATM_ACTION_MAGIC
2525 db 0fh, 0bh ; illegal instr (hardcoded assumption in PATMHandleIllegalInstrTrap)
2526 pop ecx
2527 pop eax
2528%endif
2529 popf
2530 mov dword [ss:PATM_INTERRUPTFLAG], 1
2531 ; IF=1 -> we can safely jump back to the original instruction
2532 DB 0xE9
2533PATMCheckIF_Jump:
2534 DD PATM_JUMPDELTA
2535PATMCheckIF_End:
2536ENDPROC PATMCheckIF
2537
2538SECTION .data
2539; Patch record for call instructions
2540GLOBALNAME PATMCheckIFRecord
2541 RTCCPTR_DEF PATMCheckIF_Start
2542 DD PATMCheckIF_Jump - PATMCheckIF_Start
2543 DD 0
2544 DD 0
2545 DD PATMCheckIF_End - PATMCheckIF_Start
2546%ifdef PATM_LOG_PATCHINSTR
2547 DD 6
2548%else
2549 DD 5
2550%endif
2551 DD PATM_INTERRUPTFLAG
2552 DD 0
2553 DD PATM_VMFLAGS
2554 DD 0
2555 DD PATM_INTERRUPTFLAG
2556 DD 0
2557 DD PATM_STACKPTR
2558 DD 0
2559%ifdef PATM_LOG_PATCHINSTR
2560 DD PATM_PENDINGACTION
2561 DD 0
2562%endif
2563 DD PATM_INTERRUPTFLAG
2564 DD 0
2565 DD 0ffffffffh
2566SECTION .text
2567
2568;
2569; Jump back to guest if IF=1, else fault
2570;
2571BEGINPROC PATMJumpToGuest_IF1
2572PATMJumpToGuest_IF1_Start:
2573 mov dword [ss:PATM_INTERRUPTFLAG], 0
2574 pushf
2575 test dword [ss:PATM_VMFLAGS], X86_EFL_IF
2576 jnz PATMJumpToGuest_IF1_Safe
2577 nop
2578
2579 ; IF=0 -> unsafe, so fault
2580 popf
2581 mov dword [ss:PATM_INTERRUPTFLAG], 1
2582 PATM_INT3
2583
2584PATMJumpToGuest_IF1_Safe:
2585 ; IF=1 -> we can safely jump back to the original instruction
2586 popf
2587 mov dword [ss:PATM_INTERRUPTFLAG], 1
2588 DB 0xE9
2589PATMJumpToGuest_IF1_Jump:
2590 DD PATM_JUMPDELTA
2591PATMJumpToGuest_IF1_End:
2592ENDPROC PATMJumpToGuest_IF1
2593
2594SECTION .data
2595; Patch record for call instructions
2596GLOBALNAME PATMJumpToGuest_IF1Record
2597 RTCCPTR_DEF PATMJumpToGuest_IF1_Start
2598 DD PATMJumpToGuest_IF1_Jump - PATMJumpToGuest_IF1_Start
2599 DD 0
2600 DD 0
2601 DD PATMJumpToGuest_IF1_End - PATMJumpToGuest_IF1_Start
2602 DD 4
2603 DD PATM_INTERRUPTFLAG
2604 DD 0
2605 DD PATM_VMFLAGS
2606 DD 0
2607 DD PATM_INTERRUPTFLAG
2608 DD 0
2609 DD PATM_INTERRUPTFLAG
2610 DD 0
2611 DD 0ffffffffh
2612SECTION .text
2613
2614
2615; check and correct RPL of pushed ss
2616BEGINPROC PATMMovFromSS
2617PATMMovFromSS_Start:
2618 push eax
2619 pushfd
2620 mov ax, ss
2621 and ax, 3
2622 cmp ax, 1
2623 jne near PATMMovFromSS_Continue
2624
2625 and dword [esp+8], ~3 ; clear RPL 1
2626PATMMovFromSS_Continue:
2627 popfd
2628 pop eax
2629PATMMovFromSS_Start_End:
2630ENDPROC PATMMovFromSS
2631
2632SECTION .data
2633GLOBALNAME PATMMovFromSSRecord
2634 RTCCPTR_DEF PATMMovFromSS_Start
2635 DD 0
2636 DD 0
2637 DD 0
2638 DD PATMMovFromSS_Start_End - PATMMovFromSS_Start
2639 DD 0
2640 DD 0ffffffffh
2641
2642
2643
2644
2645SECTION .rodata
2646; For assertion during init (to make absolutely sure the flags are in sync in vm.mac & vm.h)
2647GLOBALNAME PATMInterruptFlag
2648 DD VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_TIMER | VMCPU_FF_REQUEST
2649
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