@samitouri / QOSamiQemu / commits / e932132963

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;