target/i386/tcg/sysemu: Allow 32-bit SMM code to be used in the 64-bit binary
This is a preparation for the QEMU universal binary where we might want to support both, the x86_64 and the i386 target, in one binary. Instead of using #ifdef TARGET_X86_64 here, check the LM bit to select the 32-bit or 64-bit code during runtime. Signed-off-by: Thomas Huth <thuth@redhat.com> Message-ID: <20260325120944.29391-3-thuth@redhat.com>
Thomas Huth committed
Mar 25, 2026 at 13:09 UTC
e93213296310426bb5bbcac5f4d116291bf3793e
1 file changed
+43
-22
target/i386/tcg/system/smm_helper.c
+43
-22
@@ -23,24 +23,15 @@
23
#include "exec/log.h"
24
#include "tcg/helper-tcg.h"
25
26
-
27
-/* SMM support */
28
-
29
-#ifdef TARGET_X86_64
30
-#define SMM_REVISION_ID 0x00020064
31
-#else
32
-#define SMM_REVISION_ID 0x00020000
33
-#endif
34
-
35
-static void sm_state_init(X86CPU *cpu)
26
+static void sm_state_init_64(X86CPU *cpu)
27
{
28
+#ifdef TARGET_X86_64
29
CPUX86State *env = &cpu->env;
30
CPUState *cs = CPU(cpu);
31
SegmentCache *dt;
32
int i, offset;
33
target_ulong sm_state = env->smbase + 0x8000;
34
43
-#ifdef TARGET_X86_64
35
for (i = 0; i < 6; i++) {
36
dt = &env->segs[i];
37
offset = 0x7e00 + i * 16;
@@ -92,9 +83,21 @@ static void sm_state_init(X86CPU *cpu)
83
x86_stq_phys(cs, sm_state + 0x7f50, env->cr[3]);
84
x86_stl_phys(cs, sm_state + 0x7f58, env->cr[0]);
85
95
- x86_stl_phys(cs, sm_state + 0x7efc, SMM_REVISION_ID);
86
+ x86_stl_phys(cs, sm_state + 0x7efc, 0x00020064); /* SMM revision ID */
87
x86_stl_phys(cs, sm_state + 0x7f00, env->smbase);
88
#else
89
+ g_assert_not_reached();
90
+#endif
91
+}
92
+
93
+static void sm_state_init_32(X86CPU *cpu)
94
+{
95
+ CPUX86State *env = &cpu->env;
96
+ CPUState *cs = CPU(cpu);
97
+ SegmentCache *dt;
98
+ int i, offset;
99
+ target_ulong sm_state = env->smbase + 0x8000;
100
+
101
x86_stl_phys(cs, sm_state + 0x7ffc, env->cr[0]);
102
x86_stl_phys(cs, sm_state + 0x7ff8, env->cr[3]);
103
x86_stl_phys(cs, sm_state + 0x7ff4, cpu_compute_eflags(env));
@@ -140,9 +143,8 @@ static void sm_state_init(X86CPU *cpu)
143
}
144
x86_stl_phys(cs, sm_state + 0x7f14, env->cr[4]);
145
143
- x86_stl_phys(cs, sm_state + 0x7efc, SMM_REVISION_ID);
146
+ x86_stl_phys(cs, sm_state + 0x7efc, 0x00020000); /* SMM revision ID */
147
x86_stl_phys(cs, sm_state + 0x7ef8, env->smbase);
145
-#endif
148
}
149
150
void do_smm_enter(X86CPU *cpu)
@@ -160,13 +162,15 @@ void do_smm_enter(X86CPU *cpu)
162
env->hflags2 |= HF2_NMI_MASK;
163
}
164
163
- sm_state_init(cpu);
165
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
166
+ sm_state_init_64(cpu);
167
+ cpu_load_efer(env, 0);
168
+ } else {
169
+ sm_state_init_32(cpu);
170
+ }
171
172
/* init SMM cpu state */
173
167
-#ifdef TARGET_X86_64
168
- cpu_load_efer(env, 0);
169
-#endif
174
cpu_load_eflags(env, 0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C |
175
DF_MASK));
176
env->eip = 0x00008000;
@@ -197,15 +201,16 @@ void do_smm_enter(X86CPU *cpu)
201
DESC_G_MASK | DESC_A_MASK);
202
}
203
200
-static void rsm_load_regs(CPUX86State *env)
204
+static void rsm_load_regs_64(CPUX86State *env)
205
{
206
+#ifdef TARGET_X86_64
207
CPUState *cs = env_cpu(env);
208
target_ulong sm_state;
209
int i, offset;
210
uint32_t val;
211
212
sm_state = env->smbase + 0x8000;
208
-#ifdef TARGET_X86_64
213
+
214
cpu_load_efer(env, x86_ldq_phys(cs, sm_state + 0x7ed0));
215
216
env->gdt.base = x86_ldq_phys(cs, sm_state + 0x7e68);
@@ -260,6 +265,19 @@ static void rsm_load_regs(CPUX86State *env)
265
env->smbase = x86_ldl_phys(cs, sm_state + 0x7f00);
266
}
267
#else
268
+ g_assert_not_reached();
269
+#endif
270
+}
271
+
272
+static void rsm_load_regs_32(CPUX86State *env)
273
+{
274
+ CPUState *cs = env_cpu(env);
275
+ target_ulong sm_state;
276
+ int i, offset;
277
+ uint32_t val;
278
+
279
+ sm_state = env->smbase + 0x8000;
280
+
281
cpu_x86_update_cr0(env, x86_ldl_phys(cs, sm_state + 0x7ffc));
282
cpu_x86_update_cr3(env, x86_ldl_phys(cs, sm_state + 0x7ff8));
283
cpu_load_eflags(env, x86_ldl_phys(cs, sm_state + 0x7ff4),
@@ -312,14 +330,17 @@ static void rsm_load_regs(CPUX86State *env)
330
if (val & 0x20000) {
331
env->smbase = x86_ldl_phys(cs, sm_state + 0x7ef8);
332
}
315
-#endif
333
}
334
335
void helper_rsm(CPUX86State *env)
336
{
337
X86CPU *cpu = env_archcpu(env);
338
322
- rsm_load_regs(env);
339
+ if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
340
+ rsm_load_regs_64(env);
341
+ } else {
342
+ rsm_load_regs_32(env);
343
+ }
344
345
if ((env->hflags2 & HF2_SMM_INSIDE_NMI_MASK) == 0) {
346
env->hflags2 &= ~HF2_NMI_MASK;