Commit 3b21e03e043236a0569383ff5d677c336e3d8b3a

Authored by bellard
1 parent ba863458

added SMM support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2169 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
@@ -762,6 +762,7 @@ extern int code_copy_enabled; @@ -762,6 +762,7 @@ extern int code_copy_enabled;
762 #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ 762 #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
763 #define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */ 763 #define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
764 #define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */ 764 #define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
  765 +#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
765 766
766 void cpu_interrupt(CPUState *s, int mask); 767 void cpu_interrupt(CPUState *s, int mask);
767 void cpu_reset_interrupt(CPUState *env, int mask); 768 void cpu_reset_interrupt(CPUState *env, int mask);
@@ -839,6 +840,7 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); @@ -839,6 +840,7 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
839 void cpu_register_physical_memory(target_phys_addr_t start_addr, 840 void cpu_register_physical_memory(target_phys_addr_t start_addr,
840 unsigned long size, 841 unsigned long size,
841 unsigned long phys_offset); 842 unsigned long phys_offset);
  843 +uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
842 int cpu_register_io_memory(int io_index, 844 int cpu_register_io_memory(int io_index,
843 CPUReadMemoryFunc **mem_read, 845 CPUReadMemoryFunc **mem_read,
844 CPUWriteMemoryFunc **mem_write, 846 CPUWriteMemoryFunc **mem_write,
cpu-exec.c
@@ -458,8 +458,16 @@ int cpu_exec(CPUState *env1) @@ -458,8 +458,16 @@ int cpu_exec(CPUState *env1)
458 interrupt_request = env->interrupt_request; 458 interrupt_request = env->interrupt_request;
459 if (__builtin_expect(interrupt_request, 0)) { 459 if (__builtin_expect(interrupt_request, 0)) {
460 #if defined(TARGET_I386) 460 #if defined(TARGET_I386)
461 - /* if hardware interrupt pending, we execute it */  
462 - if ((interrupt_request & CPU_INTERRUPT_HARD) && 461 + if ((interrupt_request & CPU_INTERRUPT_SMI) &&
  462 + !(env->hflags & HF_SMM_MASK)) {
  463 + env->interrupt_request &= ~CPU_INTERRUPT_SMI;
  464 + do_smm_enter();
  465 +#if defined(__sparc__) && !defined(HOST_SOLARIS)
  466 + tmp_T0 = 0;
  467 +#else
  468 + T0 = 0;
  469 +#endif
  470 + } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
463 (env->eflags & IF_MASK) && 471 (env->eflags & IF_MASK) &&
464 !(env->hflags & HF_INHIBIT_IRQ_MASK)) { 472 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
465 int intno; 473 int intno;
target-i386/cpu.h
@@ -142,6 +142,7 @@ @@ -142,6 +142,7 @@
142 #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */ 142 #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */
143 #define HF_VM_SHIFT 17 /* must be same as eflags */ 143 #define HF_VM_SHIFT 17 /* must be same as eflags */
144 #define HF_HALTED_SHIFT 18 /* CPU halted */ 144 #define HF_HALTED_SHIFT 18 /* CPU halted */
  145 +#define HF_SMM_SHIFT 19 /* CPU in SMM mode */
145 146
146 #define HF_CPL_MASK (3 << HF_CPL_SHIFT) 147 #define HF_CPL_MASK (3 << HF_CPL_SHIFT)
147 #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) 148 #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
@@ -158,6 +159,7 @@ @@ -158,6 +159,7 @@
158 #define HF_CS64_MASK (1 << HF_CS64_SHIFT) 159 #define HF_CS64_MASK (1 << HF_CS64_SHIFT)
159 #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) 160 #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)
160 #define HF_HALTED_MASK (1 << HF_HALTED_SHIFT) 161 #define HF_HALTED_MASK (1 << HF_HALTED_SHIFT)
  162 +#define HF_SMM_MASK (1 << HF_SMM_SHIFT)
161 163
162 #define CR0_PE_MASK (1 << 0) 164 #define CR0_PE_MASK (1 << 0)
163 #define CR0_MP_MASK (1 << 1) 165 #define CR0_MP_MASK (1 << 1)
@@ -503,6 +505,7 @@ typedef struct CPUX86State { @@ -503,6 +505,7 @@ typedef struct CPUX86State {
503 int exception_is_int; 505 int exception_is_int;
504 target_ulong exception_next_eip; 506 target_ulong exception_next_eip;
505 target_ulong dr[8]; /* debug registers */ 507 target_ulong dr[8]; /* debug registers */
  508 + uint32_t smbase;
506 int interrupt_request; 509 int interrupt_request;
507 int user_mode_only; /* user mode only simulation */ 510 int user_mode_only; /* user mode only simulation */
508 511
@@ -630,6 +633,7 @@ void cpu_set_apic_tpr(CPUX86State *env, uint8_t val); @@ -630,6 +633,7 @@ void cpu_set_apic_tpr(CPUX86State *env, uint8_t val);
630 #ifndef NO_CPU_IO_DEFS 633 #ifndef NO_CPU_IO_DEFS
631 uint8_t cpu_get_apic_tpr(CPUX86State *env); 634 uint8_t cpu_get_apic_tpr(CPUX86State *env);
632 #endif 635 #endif
  636 +void cpu_smm_update(CPUX86State *env);
633 637
634 /* will be suppressed */ 638 /* will be suppressed */
635 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); 639 void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
target-i386/exec.h
@@ -176,6 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code, @@ -176,6 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
176 int next_eip_addend); 176 int next_eip_addend);
177 void raise_exception_err(int exception_index, int error_code); 177 void raise_exception_err(int exception_index, int error_code);
178 void raise_exception(int exception_index); 178 void raise_exception(int exception_index);
  179 +void do_smm_enter(void);
179 void __hidden cpu_loop_exit(void); 180 void __hidden cpu_loop_exit(void);
180 181
181 void OPPROTO op_movl_eflags_T0(void); 182 void OPPROTO op_movl_eflags_T0(void);
@@ -203,6 +204,7 @@ void helper_lsl(void); @@ -203,6 +204,7 @@ void helper_lsl(void);
203 void helper_lar(void); 204 void helper_lar(void);
204 void helper_verr(void); 205 void helper_verr(void);
205 void helper_verw(void); 206 void helper_verw(void);
  207 +void helper_rsm(void);
206 208
207 void check_iob_T0(void); 209 void check_iob_T0(void);
208 void check_iow_T0(void); 210 void check_iow_T0(void);
target-i386/helper.c
@@ -1215,6 +1215,269 @@ void raise_exception(int exception_index) @@ -1215,6 +1215,269 @@ void raise_exception(int exception_index)
1215 raise_interrupt(exception_index, 0, 0, 0); 1215 raise_interrupt(exception_index, 0, 0, 0);
1216 } 1216 }
1217 1217
  1218 +/* SMM support */
  1219 +
  1220 +#ifdef TARGET_X86_64
  1221 +#define SMM_REVISION_ID 0x00020064
  1222 +#else
  1223 +#define SMM_REVISION_ID 0x00020000
  1224 +#endif
  1225 +
  1226 +void do_smm_enter(void)
  1227 +{
  1228 + target_ulong sm_state;
  1229 + SegmentCache *dt;
  1230 + int i, offset;
  1231 +
  1232 + if (loglevel & CPU_LOG_INT) {
  1233 + fprintf(logfile, "SMM: enter\n");
  1234 + cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
  1235 + }
  1236 +
  1237 + env->hflags |= HF_SMM_MASK;
  1238 + cpu_smm_update(env);
  1239 +
  1240 + sm_state = env->smbase + 0x8000;
  1241 +
  1242 +#ifdef TARGET_X86_64
  1243 + for(i = 0; i < 6; i++) {
  1244 + dt = &env->segs[i];
  1245 + offset = 0x7e00 + i * 16;
  1246 + stw_phys(sm_state + offset, dt->selector);
  1247 + stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
  1248 + stl_phys(sm_state + offset + 4, dt->limit);
  1249 + stq_phys(sm_state + offset + 8, dt->base);
  1250 + }
  1251 +
  1252 + stq_phys(sm_state + 0x7e68, env->gdt.base);
  1253 + stl_phys(sm_state + 0x7e64, env->gdt.limit);
  1254 +
  1255 + stw_phys(sm_state + 0x7e70, env->ldt.selector);
  1256 + stq_phys(sm_state + 0x7e78, env->ldt.base);
  1257 + stl_phys(sm_state + 0x7e74, env->ldt.limit);
  1258 + stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
  1259 +
  1260 + stq_phys(sm_state + 0x7e88, env->idt.base);
  1261 + stl_phys(sm_state + 0x7e84, env->idt.limit);
  1262 +
  1263 + stw_phys(sm_state + 0x7e90, env->tr.selector);
  1264 + stq_phys(sm_state + 0x7e98, env->tr.base);
  1265 + stl_phys(sm_state + 0x7e94, env->tr.limit);
  1266 + stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
  1267 +
  1268 + stq_phys(sm_state + 0x7ed0, env->efer);
  1269 +
  1270 + stq_phys(sm_state + 0x7ff8, EAX);
  1271 + stq_phys(sm_state + 0x7ff0, ECX);
  1272 + stq_phys(sm_state + 0x7fe8, EDX);
  1273 + stq_phys(sm_state + 0x7fe0, EBX);
  1274 + stq_phys(sm_state + 0x7fd8, ESP);
  1275 + stq_phys(sm_state + 0x7fd0, EBP);
  1276 + stq_phys(sm_state + 0x7fc8, ESI);
  1277 + stq_phys(sm_state + 0x7fc0, EDI);
  1278 + for(i = 8; i < 16; i++)
  1279 + stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
  1280 + stq_phys(sm_state + 0x7f78, env->eip);
  1281 + stl_phys(sm_state + 0x7f70, compute_eflags());
  1282 + stl_phys(sm_state + 0x7f68, env->dr[6]);
  1283 + stl_phys(sm_state + 0x7f60, env->dr[7]);
  1284 +
  1285 + stl_phys(sm_state + 0x7f48, env->cr[4]);
  1286 + stl_phys(sm_state + 0x7f50, env->cr[3]);
  1287 + stl_phys(sm_state + 0x7f58, env->cr[0]);
  1288 +
  1289 + stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
  1290 + stl_phys(sm_state + 0x7f00, env->smbase);
  1291 +#else
  1292 + stl_phys(sm_state + 0x7ffc, env->cr[0]);
  1293 + stl_phys(sm_state + 0x7ff8, env->cr[3]);
  1294 + stl_phys(sm_state + 0x7ff4, compute_eflags());
  1295 + stl_phys(sm_state + 0x7ff0, env->eip);
  1296 + stl_phys(sm_state + 0x7fec, EDI);
  1297 + stl_phys(sm_state + 0x7fe8, ESI);
  1298 + stl_phys(sm_state + 0x7fe4, EBP);
  1299 + stl_phys(sm_state + 0x7fe0, ESP);
  1300 + stl_phys(sm_state + 0x7fdc, EBX);
  1301 + stl_phys(sm_state + 0x7fd8, EDX);
  1302 + stl_phys(sm_state + 0x7fd4, ECX);
  1303 + stl_phys(sm_state + 0x7fd0, EAX);
  1304 + stl_phys(sm_state + 0x7fcc, env->dr[6]);
  1305 + stl_phys(sm_state + 0x7fc8, env->dr[7]);
  1306 +
  1307 + stl_phys(sm_state + 0x7fc4, env->tr.selector);
  1308 + stl_phys(sm_state + 0x7f64, env->tr.base);
  1309 + stl_phys(sm_state + 0x7f60, env->tr.limit);
  1310 + stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
  1311 +
  1312 + stl_phys(sm_state + 0x7fc0, env->ldt.selector);
  1313 + stl_phys(sm_state + 0x7f80, env->ldt.base);
  1314 + stl_phys(sm_state + 0x7f7c, env->ldt.limit);
  1315 + stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
  1316 +
  1317 + stl_phys(sm_state + 0x7f74, env->gdt.base);
  1318 + stl_phys(sm_state + 0x7f70, env->gdt.limit);
  1319 +
  1320 + stl_phys(sm_state + 0x7f58, env->idt.base);
  1321 + stl_phys(sm_state + 0x7f54, env->idt.limit);
  1322 +
  1323 + for(i = 0; i < 6; i++) {
  1324 + dt = &env->segs[i];
  1325 + if (i < 3)
  1326 + offset = 0x7f84 + i * 12;
  1327 + else
  1328 + offset = 0x7f2c + (i - 3) * 12;
  1329 + stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
  1330 + stl_phys(sm_state + offset + 8, dt->base);
  1331 + stl_phys(sm_state + offset + 4, dt->limit);
  1332 + stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
  1333 + }
  1334 + stl_phys(sm_state + 0x7f14, env->cr[4]);
  1335 +
  1336 + stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
  1337 + stl_phys(sm_state + 0x7ef8, env->smbase);
  1338 +#endif
  1339 + /* init SMM cpu state */
  1340 +
  1341 + load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
  1342 + env->eip = 0x00008000;
  1343 + cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
  1344 + 0xffffffff, 0);
  1345 + cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
  1346 + cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
  1347 + cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
  1348 + cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
  1349 + cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
  1350 +
  1351 + cpu_x86_update_cr0(env,
  1352 + env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
  1353 + cpu_x86_update_cr4(env, 0);
  1354 + env->dr[7] = 0x00000400;
  1355 +#ifdef TARGET_X86_64
  1356 + env->efer = 0;
  1357 +#endif
  1358 + CC_OP = CC_OP_EFLAGS;
  1359 +}
  1360 +
  1361 +void helper_rsm(void)
  1362 +{
  1363 + target_ulong sm_state;
  1364 + int i, offset;
  1365 + uint32_t val;
  1366 +
  1367 + sm_state = env->smbase + 0x8000;
  1368 +#ifdef TARGET_X86_64
  1369 + for(i = 0; i < 6; i++) {
  1370 + offset = 0x7e00 + i * 16;
  1371 + cpu_x86_load_seg_cache(env, i,
  1372 + lduw_phys(sm_state + offset),
  1373 + ldq_phys(sm_state + offset + 8),
  1374 + ldl_phys(sm_state + offset + 4),
  1375 + (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
  1376 + }
  1377 +
  1378 + env->gdt.base = ldq_phys(sm_state + 0x7e68);
  1379 + env->gdt.limit = ldl_phys(sm_state + 0x7e64);
  1380 +
  1381 + env->ldt.selector = lduw_phys(sm_state + 0x7e70);
  1382 + env->ldt.base = ldq_phys(sm_state + 0x7e78);
  1383 + env->ldt.limit = ldl_phys(sm_state + 0x7e74);
  1384 + env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
  1385 +
  1386 + env->idt.base = ldq_phys(sm_state + 0x7e88);
  1387 + env->idt.limit = ldl_phys(sm_state + 0x7e84);
  1388 +
  1389 + env->tr.selector = lduw_phys(sm_state + 0x7e90);
  1390 + env->tr.base = ldq_phys(sm_state + 0x7e98);
  1391 + env->tr.limit = ldl_phys(sm_state + 0x7e94);
  1392 + env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
  1393 +
  1394 + env->efer = ldq_phys(sm_state + 0x7ed0);
  1395 +
  1396 + EAX = ldq_phys(sm_state + 0x7ff8);
  1397 + ECX = ldq_phys(sm_state + 0x7ff0);
  1398 + EDX = ldq_phys(sm_state + 0x7fe8);
  1399 + EBX = ldq_phys(sm_state + 0x7fe0);
  1400 + ESP = ldq_phys(sm_state + 0x7fd8);
  1401 + EBP = ldq_phys(sm_state + 0x7fd0);
  1402 + ESI = ldq_phys(sm_state + 0x7fc8);
  1403 + EDI = ldq_phys(sm_state + 0x7fc0);
  1404 + for(i = 8; i < 16; i++)
  1405 + env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
  1406 + env->eip = ldq_phys(sm_state + 0x7f78);
  1407 + load_eflags(ldl_phys(sm_state + 0x7f70),
  1408 + ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
  1409 + env->dr[6] = ldl_phys(sm_state + 0x7f68);
  1410 + env->dr[7] = ldl_phys(sm_state + 0x7f60);
  1411 +
  1412 + cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
  1413 + cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
  1414 + cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
  1415 +
  1416 + val = ldl_phys(sm_state + 0x7efc); /* revision ID */
  1417 + if (val & 0x20000) {
  1418 + env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
  1419 + }
  1420 +#else
  1421 + cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
  1422 + cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
  1423 + load_eflags(ldl_phys(sm_state + 0x7ff4),
  1424 + ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
  1425 + env->eip = ldl_phys(sm_state + 0x7ff0);
  1426 + EDI = ldl_phys(sm_state + 0x7fec);
  1427 + ESI = ldl_phys(sm_state + 0x7fe8);
  1428 + EBP = ldl_phys(sm_state + 0x7fe4);
  1429 + ESP = ldl_phys(sm_state + 0x7fe0);
  1430 + EBX = ldl_phys(sm_state + 0x7fdc);
  1431 + EDX = ldl_phys(sm_state + 0x7fd8);
  1432 + ECX = ldl_phys(sm_state + 0x7fd4);
  1433 + EAX = ldl_phys(sm_state + 0x7fd0);
  1434 + env->dr[6] = ldl_phys(sm_state + 0x7fcc);
  1435 + env->dr[7] = ldl_phys(sm_state + 0x7fc8);
  1436 +
  1437 + env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
  1438 + env->tr.base = ldl_phys(sm_state + 0x7f64);
  1439 + env->tr.limit = ldl_phys(sm_state + 0x7f60);
  1440 + env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
  1441 +
  1442 + env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
  1443 + env->ldt.base = ldl_phys(sm_state + 0x7f80);
  1444 + env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
  1445 + env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
  1446 +
  1447 + env->gdt.base = ldl_phys(sm_state + 0x7f74);
  1448 + env->gdt.limit = ldl_phys(sm_state + 0x7f70);
  1449 +
  1450 + env->idt.base = ldl_phys(sm_state + 0x7f58);
  1451 + env->idt.limit = ldl_phys(sm_state + 0x7f54);
  1452 +
  1453 + for(i = 0; i < 6; i++) {
  1454 + if (i < 3)
  1455 + offset = 0x7f84 + i * 12;
  1456 + else
  1457 + offset = 0x7f2c + (i - 3) * 12;
  1458 + cpu_x86_load_seg_cache(env, i,
  1459 + ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
  1460 + ldl_phys(sm_state + offset + 8),
  1461 + ldl_phys(sm_state + offset + 4),
  1462 + (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
  1463 + }
  1464 + cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
  1465 +
  1466 + val = ldl_phys(sm_state + 0x7efc); /* revision ID */
  1467 + if (val & 0x20000) {
  1468 + env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
  1469 + }
  1470 +#endif
  1471 + CC_OP = CC_OP_EFLAGS;
  1472 + env->hflags &= ~HF_SMM_MASK;
  1473 + cpu_smm_update(env);
  1474 +
  1475 + if (loglevel & CPU_LOG_INT) {
  1476 + fprintf(logfile, "SMM: after RSM\n");
  1477 + cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
  1478 + }
  1479 +}
  1480 +
1218 #ifdef BUGGY_GCC_DIV64 1481 #ifdef BUGGY_GCC_DIV64
1219 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we 1482 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1220 call it from another function */ 1483 call it from another function */
target-i386/helper2.c
@@ -161,7 +161,8 @@ void cpu_reset(CPUX86State *env) @@ -161,7 +161,8 @@ void cpu_reset(CPUX86State *env)
161 161
162 cpu_x86_update_cr0(env, 0x60000010); 162 cpu_x86_update_cr0(env, 0x60000010);
163 env->a20_mask = 0xffffffff; 163 env->a20_mask = 0xffffffff;
164 - 164 + env->smbase = 0x30000;
  165 +
165 env->idt.limit = 0xffff; 166 env->idt.limit = 0xffff;
166 env->gdt.limit = 0xffff; 167 env->gdt.limit = 0xffff;
167 env->ldt.limit = 0xffff; 168 env->ldt.limit = 0xffff;
@@ -268,7 +269,7 @@ void cpu_dump_state(CPUState *env, FILE *f, @@ -268,7 +269,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
268 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n" 269 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
269 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n" 270 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
270 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n" 271 "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n"
271 - "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n", 272 + "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
272 env->regs[R_EAX], 273 env->regs[R_EAX],
273 env->regs[R_EBX], 274 env->regs[R_EBX],
274 env->regs[R_ECX], 275 env->regs[R_ECX],
@@ -296,13 +297,14 @@ void cpu_dump_state(CPUState *env, FILE *f, @@ -296,13 +297,14 @@ void cpu_dump_state(CPUState *env, FILE *f,
296 env->hflags & HF_CPL_MASK, 297 env->hflags & HF_CPL_MASK,
297 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, 298 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
298 (env->a20_mask >> 20) & 1, 299 (env->a20_mask >> 20) & 1,
  300 + (env->hflags >> HF_SMM_SHIFT) & 1,
299 (env->hflags >> HF_HALTED_SHIFT) & 1); 301 (env->hflags >> HF_HALTED_SHIFT) & 1);
300 } else 302 } else
301 #endif 303 #endif
302 { 304 {
303 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" 305 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
304 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" 306 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
305 - "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d HLT=%d\n", 307 + "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n",
306 (uint32_t)env->regs[R_EAX], 308 (uint32_t)env->regs[R_EAX],
307 (uint32_t)env->regs[R_EBX], 309 (uint32_t)env->regs[R_EBX],
308 (uint32_t)env->regs[R_ECX], 310 (uint32_t)env->regs[R_ECX],
@@ -322,6 +324,7 @@ void cpu_dump_state(CPUState *env, FILE *f, @@ -322,6 +324,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
322 env->hflags & HF_CPL_MASK, 324 env->hflags & HF_CPL_MASK,
323 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, 325 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
324 (env->a20_mask >> 20) & 1, 326 (env->a20_mask >> 20) & 1,
  327 + (env->hflags >> HF_SMM_SHIFT) & 1,
325 (env->hflags >> HF_HALTED_SHIFT) & 1); 328 (env->hflags >> HF_HALTED_SHIFT) & 1);
326 } 329 }
327 330
target-i386/op.c
@@ -678,6 +678,11 @@ void OPPROTO op_reset_inhibit_irq(void) @@ -678,6 +678,11 @@ void OPPROTO op_reset_inhibit_irq(void)
678 env->hflags &= ~HF_INHIBIT_IRQ_MASK; 678 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
679 } 679 }
680 680
  681 +void OPPROTO op_rsm(void)
  682 +{
  683 + helper_rsm();
  684 +}
  685 +
681 #if 0 686 #if 0
682 /* vm86plus instructions */ 687 /* vm86plus instructions */
683 void OPPROTO op_cli_vm(void) 688 void OPPROTO op_cli_vm(void)
target-i386/translate.c
@@ -6012,6 +6012,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) @@ -6012,6 +6012,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
6012 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); 6012 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6013 /* ignore for now */ 6013 /* ignore for now */
6014 break; 6014 break;
  6015 + case 0x1aa: /* rsm */
  6016 + if (!(s->flags & HF_SMM_MASK))
  6017 + goto illegal_op;
  6018 + if (s->cc_op != CC_OP_DYNAMIC) {
  6019 + gen_op_set_cc_op(s->cc_op);
  6020 + s->cc_op = CC_OP_DYNAMIC;
  6021 + }
  6022 + gen_jmp_im(s->pc - s->cs_base);
  6023 + gen_op_rsm();
  6024 + gen_eob(s);
  6025 + break;
6015 case 0x110 ... 0x117: 6026 case 0x110 ... 0x117:
6016 case 0x128 ... 0x12f: 6027 case 0x128 ... 0x12f:
6017 case 0x150 ... 0x177: 6028 case 0x150 ... 0x177:
@@ -4881,6 +4881,7 @@ void cpu_save(QEMUFile *f, void *opaque) @@ -4881,6 +4881,7 @@ void cpu_save(QEMUFile *f, void *opaque)
4881 qemu_put_be64s(f, &env->fmask); 4881 qemu_put_be64s(f, &env->fmask);
4882 qemu_put_be64s(f, &env->kernelgsbase); 4882 qemu_put_be64s(f, &env->kernelgsbase);
4883 #endif 4883 #endif
  4884 + qemu_put_be32s(f, &env->smbase);
4884 } 4885 }
4885 4886
4886 #ifdef USE_X86LDOUBLE 4887 #ifdef USE_X86LDOUBLE
@@ -4914,7 +4915,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) @@ -4914,7 +4915,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
4914 uint32_t hflags; 4915 uint32_t hflags;
4915 uint16_t fpus, fpuc, fptag, fpregs_format; 4916 uint16_t fpus, fpuc, fptag, fpregs_format;
4916 4917
4917 - if (version_id != 3) 4918 + if (version_id != 3 && version_id != 4)
4918 return -EINVAL; 4919 return -EINVAL;
4919 for(i = 0; i < CPU_NB_REGS; i++) 4920 for(i = 0; i < CPU_NB_REGS; i++)
4920 qemu_get_betls(f, &env->regs[i]); 4921 qemu_get_betls(f, &env->regs[i]);
@@ -5017,6 +5018,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) @@ -5017,6 +5018,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
5017 qemu_get_be64s(f, &env->fmask); 5018 qemu_get_be64s(f, &env->fmask);
5018 qemu_get_be64s(f, &env->kernelgsbase); 5019 qemu_get_be64s(f, &env->kernelgsbase);
5019 #endif 5020 #endif
  5021 + if (version_id >= 4)
  5022 + qemu_get_be32s(f, &env->smbase);
5020 5023
5021 /* XXX: compute hflags from scratch, except for CPL and IIF */ 5024 /* XXX: compute hflags from scratch, except for CPL and IIF */
5022 env->hflags = hflags; 5025 env->hflags = hflags;