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 762 #define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
763 763 #define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
764 764 #define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
  765 +#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
765 766  
766 767 void cpu_interrupt(CPUState *s, int mask);
767 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 840 void cpu_register_physical_memory(target_phys_addr_t start_addr,
840 841 unsigned long size,
841 842 unsigned long phys_offset);
  843 +uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
842 844 int cpu_register_io_memory(int io_index,
843 845 CPUReadMemoryFunc **mem_read,
844 846 CPUWriteMemoryFunc **mem_write,
... ...
cpu-exec.c
... ... @@ -458,8 +458,16 @@ int cpu_exec(CPUState *env1)
458 458 interrupt_request = env->interrupt_request;
459 459 if (__builtin_expect(interrupt_request, 0)) {
460 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 471 (env->eflags & IF_MASK) &&
464 472 !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
465 473 int intno;
... ...
target-i386/cpu.h
... ... @@ -142,6 +142,7 @@
142 142 #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */
143 143 #define HF_VM_SHIFT 17 /* must be same as eflags */
144 144 #define HF_HALTED_SHIFT 18 /* CPU halted */
  145 +#define HF_SMM_SHIFT 19 /* CPU in SMM mode */
145 146  
146 147 #define HF_CPL_MASK (3 << HF_CPL_SHIFT)
147 148 #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
... ... @@ -158,6 +159,7 @@
158 159 #define HF_CS64_MASK (1 << HF_CS64_SHIFT)
159 160 #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)
160 161 #define HF_HALTED_MASK (1 << HF_HALTED_SHIFT)
  162 +#define HF_SMM_MASK (1 << HF_SMM_SHIFT)
161 163  
162 164 #define CR0_PE_MASK (1 << 0)
163 165 #define CR0_MP_MASK (1 << 1)
... ... @@ -503,6 +505,7 @@ typedef struct CPUX86State {
503 505 int exception_is_int;
504 506 target_ulong exception_next_eip;
505 507 target_ulong dr[8]; /* debug registers */
  508 + uint32_t smbase;
506 509 int interrupt_request;
507 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 633 #ifndef NO_CPU_IO_DEFS
631 634 uint8_t cpu_get_apic_tpr(CPUX86State *env);
632 635 #endif
  636 +void cpu_smm_update(CPUX86State *env);
633 637  
634 638 /* will be suppressed */
635 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 176 int next_eip_addend);
177 177 void raise_exception_err(int exception_index, int error_code);
178 178 void raise_exception(int exception_index);
  179 +void do_smm_enter(void);
179 180 void __hidden cpu_loop_exit(void);
180 181  
181 182 void OPPROTO op_movl_eflags_T0(void);
... ... @@ -203,6 +204,7 @@ void helper_lsl(void);
203 204 void helper_lar(void);
204 205 void helper_verr(void);
205 206 void helper_verw(void);
  207 +void helper_rsm(void);
206 208  
207 209 void check_iob_T0(void);
208 210 void check_iow_T0(void);
... ...
target-i386/helper.c
... ... @@ -1215,6 +1215,269 @@ void raise_exception(int exception_index)
1215 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 1481 #ifdef BUGGY_GCC_DIV64
1219 1482 /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1220 1483 call it from another function */
... ...
target-i386/helper2.c
... ... @@ -161,7 +161,8 @@ void cpu_reset(CPUX86State *env)
161 161  
162 162 cpu_x86_update_cr0(env, 0x60000010);
163 163 env->a20_mask = 0xffffffff;
164   -
  164 + env->smbase = 0x30000;
  165 +
165 166 env->idt.limit = 0xffff;
166 167 env->gdt.limit = 0xffff;
167 168 env->ldt.limit = 0xffff;
... ... @@ -268,7 +269,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
268 269 "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n"
269 270 "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n"
270 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 273 env->regs[R_EAX],
273 274 env->regs[R_EBX],
274 275 env->regs[R_ECX],
... ... @@ -296,13 +297,14 @@ void cpu_dump_state(CPUState *env, FILE *f,
296 297 env->hflags & HF_CPL_MASK,
297 298 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
298 299 (env->a20_mask >> 20) & 1,
  300 + (env->hflags >> HF_SMM_SHIFT) & 1,
299 301 (env->hflags >> HF_HALTED_SHIFT) & 1);
300 302 } else
301 303 #endif
302 304 {
303 305 cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
304 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 308 (uint32_t)env->regs[R_EAX],
307 309 (uint32_t)env->regs[R_EBX],
308 310 (uint32_t)env->regs[R_ECX],
... ... @@ -322,6 +324,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
322 324 env->hflags & HF_CPL_MASK,
323 325 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
324 326 (env->a20_mask >> 20) & 1,
  327 + (env->hflags >> HF_SMM_SHIFT) & 1,
325 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 678 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
679 679 }
680 680  
  681 +void OPPROTO op_rsm(void)
  682 +{
  683 + helper_rsm();
  684 +}
  685 +
681 686 #if 0
682 687 /* vm86plus instructions */
683 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 6012 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
6013 6013 /* ignore for now */
6014 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 6026 case 0x110 ... 0x117:
6016 6027 case 0x128 ... 0x12f:
6017 6028 case 0x150 ... 0x177:
... ...
... ... @@ -4881,6 +4881,7 @@ void cpu_save(QEMUFile *f, void *opaque)
4881 4881 qemu_put_be64s(f, &env->fmask);
4882 4882 qemu_put_be64s(f, &env->kernelgsbase);
4883 4883 #endif
  4884 + qemu_put_be32s(f, &env->smbase);
4884 4885 }
4885 4886  
4886 4887 #ifdef USE_X86LDOUBLE
... ... @@ -4914,7 +4915,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
4914 4915 uint32_t hflags;
4915 4916 uint16_t fpus, fpuc, fptag, fpregs_format;
4916 4917  
4917   - if (version_id != 3)
  4918 + if (version_id != 3 && version_id != 4)
4918 4919 return -EINVAL;
4919 4920 for(i = 0; i < CPU_NB_REGS; i++)
4920 4921 qemu_get_betls(f, &env->regs[i]);
... ... @@ -5017,6 +5018,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
5017 5018 qemu_get_be64s(f, &env->fmask);
5018 5019 qemu_get_be64s(f, &env->kernelgsbase);
5019 5020 #endif
  5021 + if (version_id >= 4)
  5022 + qemu_get_be32s(f, &env->smbase);
5020 5023  
5021 5024 /* XXX: compute hflags from scratch, except for CPL and IIF */
5022 5025 env->hflags = hflags;
... ...