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; | ... | ... |