Commit 3b21e03e043236a0569383ff5d677c336e3d8b3a
1 parent
ba863458
added SMM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2169 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
9 changed files
with
307 additions
and
6 deletions
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
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, ®_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: | ... | ... |
vl.c
... | ... | @@ -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; | ... | ... |