VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/CpuHotplugSmm/FirstSmiHandler.nasm@ 99404

Last change on this file since 99404 was 99404, checked in by vboxsync, 20 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-asm
File size: 3.8 KB
Line 
1;------------------------------------------------------------------------------
2; @file
3; Relocate the SMBASE on a hot-added CPU when it services its first SMI.
4;
5; Copyright (c) 2020, Red Hat, Inc.
6;
7; SPDX-License-Identifier: BSD-2-Clause-Patent
8;
9; The routine runs on the hot-added CPU in the following "big real mode",
10; 16-bit environment; per "SMI HANDLER EXECUTION ENVIRONMENT" in the Intel SDM
11; (table "Processor Register Initialization in SMM"):
12;
13; - CS selector: 0x3000 (most significant 16 bits of SMM_DEFAULT_SMBASE).
14;
15; - CS limit: 0xFFFF_FFFF.
16;
17; - CS base: SMM_DEFAULT_SMBASE (0x3_0000).
18;
19; - IP: SMM_HANDLER_OFFSET (0x8000).
20;
21; - ES, SS, DS, FS, GS selectors: 0.
22;
23; - ES, SS, DS, FS, GS limits: 0xFFFF_FFFF.
24;
25; - ES, SS, DS, FS, GS bases: 0.
26;
27; - Operand-size and address-size override prefixes can be used to access the
28; address space beyond 1MB.
29;------------------------------------------------------------------------------
30
31SECTION .data
32BITS 16
33
34;
35; Bring in SMM_DEFAULT_SMBASE from
36; "MdePkg/Include/Register/Intel/SmramSaveStateMap.h".
37;
38SMM_DEFAULT_SMBASE: equ 0x3_0000
39
40;
41; Field offsets in FIRST_SMI_HANDLER_CONTEXT, which resides at
42; SMM_DEFAULT_SMBASE.
43;
44ApicIdGate: equ 0 ; UINT64
45NewSmbase: equ 8 ; UINT32
46AboutToLeaveSmm: equ 12 ; UINT8
47
48;
49; SMRAM Save State Map field offsets, per the AMD (not Intel) layout that QEMU
50; implements. Relative to SMM_DEFAULT_SMBASE.
51;
52SaveStateRevId: equ 0xFEFC ; UINT32
53SaveStateSmbase: equ 0xFEF8 ; UINT32
54SaveStateSmbase64: equ 0xFF00 ; UINT32
55
56;
57; CPUID constants, from "MdePkg/Include/Register/Intel/Cpuid.h".
58;
59CPUID_SIGNATURE: equ 0x00
60CPUID_EXTENDED_TOPOLOGY: equ 0x0B
61CPUID_VERSION_INFO: equ 0x01
62
63GLOBAL ASM_PFX (mFirstSmiHandler) ; UINT8[]
64GLOBAL ASM_PFX (mFirstSmiHandlerSize) ; UINT16
65
66ASM_PFX (mFirstSmiHandler):
67 ;
68 ; Get our own APIC ID first, so we can contend for ApicIdGate.
69 ;
70 ; This basically reimplements GetInitialApicId() from
71 ; "UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c".
72 ;
73 mov eax, CPUID_SIGNATURE
74 cpuid
75 cmp eax, CPUID_EXTENDED_TOPOLOGY
76 jb GetApicIdFromVersionInfo
77
78 mov eax, CPUID_EXTENDED_TOPOLOGY
79 mov ecx, 0
80 cpuid
81 test ebx, 0xFFFF
82 jz GetApicIdFromVersionInfo
83
84 ;
85 ; EDX has the APIC ID, save it to ESI.
86 ;
87 mov esi, edx
88 jmp KnockOnGate
89
90GetApicIdFromVersionInfo:
91 mov eax, CPUID_VERSION_INFO
92 cpuid
93 shr ebx, 24
94 ;
95 ; EBX has the APIC ID, save it to ESI.
96 ;
97 mov esi, ebx
98
99KnockOnGate:
100 ;
101 ; See if ApicIdGate shows our own APIC ID. If so, swap it to MAX_UINT64
102 ; (close the gate), and advance. Otherwise, keep knocking.
103 ;
104 ; InterlockedCompareExchange64():
105 ; - Value := &FIRST_SMI_HANDLER_CONTEXT.ApicIdGate
106 ; - CompareValue (EDX:EAX) := APIC ID (from ESI)
107 ; - ExchangeValue (ECX:EBX) := MAX_UINT64
108 ;
109 mov edx, 0
110 mov eax, esi
111 mov ecx, 0xFFFF_FFFF
112 mov ebx, 0xFFFF_FFFF
113 lock cmpxchg8b [ds : dword (SMM_DEFAULT_SMBASE + ApicIdGate)]
114 jz ApicIdMatch
115 pause
116 jmp KnockOnGate
117
118ApicIdMatch:
119 ;
120 ; Update the SMBASE field in the SMRAM Save State Map.
121 ;
122 ; First, calculate the address of the SMBASE field, based on the SMM Revision
123 ; ID; store the result in EBX.
124 ;
125 mov eax, dword [ds : dword (SMM_DEFAULT_SMBASE + SaveStateRevId)]
126 test eax, 0xFFFF
127 jz LegacySaveStateMap
128
129 mov ebx, SMM_DEFAULT_SMBASE + SaveStateSmbase64
130 jmp UpdateSmbase
131
132LegacySaveStateMap:
133 mov ebx, SMM_DEFAULT_SMBASE + SaveStateSmbase
134
135UpdateSmbase:
136 ;
137 ; Load the new SMBASE value into EAX.
138 ;
139 mov eax, dword [ds : dword (SMM_DEFAULT_SMBASE + NewSmbase)]
140 ;
141 ; Save it to the SMBASE field whose address we calculated in EBX.
142 ;
143 mov dword [ds : dword ebx], eax
144 ;
145 ; Set AboutToLeaveSmm.
146 ;
147 mov byte [ds : dword (SMM_DEFAULT_SMBASE + AboutToLeaveSmm)], 1
148 ;
149 ; We're done; leave SMM and continue to the pen.
150 ;
151 rsm
152
153ASM_PFX (mFirstSmiHandlerSize):
154 dw $ - ASM_PFX (mFirstSmiHandler)
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