void helper_rsm(CPUX86State *env) { X86CPU *cpu = x86_env_get_cpu(env); CPUState *cs = CPU(cpu); target_ulong sm_state; int i, offset; uint32_t val; sm_state = env->smbase + 0x8000; #ifdef TARGET_X86_64 cpu_load_efer(env, x86_ldq_phys(cs, sm_state + 0x7ed0)); env->gdt.base = x86_ldq_phys(cs, sm_state + 0x7e68); env->gdt.limit = x86_ldl_phys(cs, sm_state + 0x7e64); env->ldt.selector = x86_lduw_phys(cs, sm_state + 0x7e70); env->ldt.base = x86_ldq_phys(cs, sm_state + 0x7e78); env->ldt.limit = x86_ldl_phys(cs, sm_state + 0x7e74); env->ldt.flags = (x86_lduw_phys(cs, sm_state + 0x7e72) & 0xf0ff) << 8; env->idt.base = x86_ldq_phys(cs, sm_state + 0x7e88); env->idt.limit = x86_ldl_phys(cs, sm_state + 0x7e84); env->tr.selector = x86_lduw_phys(cs, sm_state + 0x7e90); env->tr.base = x86_ldq_phys(cs, sm_state + 0x7e98); env->tr.limit = x86_ldl_phys(cs, sm_state + 0x7e94); env->tr.flags = (x86_lduw_phys(cs, sm_state + 0x7e92) & 0xf0ff) << 8; env->regs[R_EAX] = x86_ldq_phys(cs, sm_state + 0x7ff8); env->regs[R_ECX] = x86_ldq_phys(cs, sm_state + 0x7ff0); env->regs[R_EDX] = x86_ldq_phys(cs, sm_state + 0x7fe8); env->regs[R_EBX] = x86_ldq_phys(cs, sm_state + 0x7fe0); env->regs[R_ESP] = x86_ldq_phys(cs, sm_state + 0x7fd8); env->regs[R_EBP] = x86_ldq_phys(cs, sm_state + 0x7fd0); env->regs[R_ESI] = x86_ldq_phys(cs, sm_state + 0x7fc8); env->regs[R_EDI] = x86_ldq_phys(cs, sm_state + 0x7fc0); for (i = 8; i < 16; i++) { env->regs[i] = x86_ldq_phys(cs, sm_state + 0x7ff8 - i * 8); } env->eip = x86_ldq_phys(cs, sm_state + 0x7f78); cpu_load_eflags(env, x86_ldl_phys(cs, sm_state + 0x7f70), ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); env->dr[6] = x86_ldl_phys(cs, sm_state + 0x7f68); env->dr[7] = x86_ldl_phys(cs, sm_state + 0x7f60); cpu_x86_update_cr4(env, x86_ldl_phys(cs, sm_state + 0x7f48)); cpu_x86_update_cr3(env, x86_ldq_phys(cs, sm_state + 0x7f50)); cpu_x86_update_cr0(env, x86_ldl_phys(cs, sm_state + 0x7f58)); for (i = 0; i < 6; i++) { offset = 0x7e00 + i * 16; cpu_x86_load_seg_cache(env, i, x86_lduw_phys(cs, sm_state + offset), x86_ldq_phys(cs, sm_state + offset + 8), x86_ldl_phys(cs, sm_state + offset + 4), (x86_lduw_phys(cs, sm_state + offset + 2) & 0xf0ff) << 8); } val = x86_ldl_phys(cs, sm_state + 0x7efc); /* revision ID */ if (val & 0x20000) { env->smbase = x86_ldl_phys(cs, sm_state + 0x7f00); } #else cpu_x86_update_cr0(env, x86_ldl_phys(cs, sm_state + 0x7ffc)); cpu_x86_update_cr3(env, x86_ldl_phys(cs, sm_state + 0x7ff8)); cpu_load_eflags(env, x86_ldl_phys(cs, sm_state + 0x7ff4), ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); env->eip = x86_ldl_phys(cs, sm_state + 0x7ff0); env->regs[R_EDI] = x86_ldl_phys(cs, sm_state + 0x7fec); env->regs[R_ESI] = x86_ldl_phys(cs, sm_state + 0x7fe8); env->regs[R_EBP] = x86_ldl_phys(cs, sm_state + 0x7fe4); env->regs[R_ESP] = x86_ldl_phys(cs, sm_state + 0x7fe0); env->regs[R_EBX] = x86_ldl_phys(cs, sm_state + 0x7fdc); env->regs[R_EDX] = x86_ldl_phys(cs, sm_state + 0x7fd8); env->regs[R_ECX] = x86_ldl_phys(cs, sm_state + 0x7fd4); env->regs[R_EAX] = x86_ldl_phys(cs, sm_state + 0x7fd0); env->dr[6] = x86_ldl_phys(cs, sm_state + 0x7fcc); env->dr[7] = x86_ldl_phys(cs, sm_state + 0x7fc8); env->tr.selector = x86_ldl_phys(cs, sm_state + 0x7fc4) & 0xffff; env->tr.base = x86_ldl_phys(cs, sm_state + 0x7f64); env->tr.limit = x86_ldl_phys(cs, sm_state + 0x7f60); env->tr.flags = (x86_ldl_phys(cs, sm_state + 0x7f5c) & 0xf0ff) << 8; env->ldt.selector = x86_ldl_phys(cs, sm_state + 0x7fc0) & 0xffff; env->ldt.base = x86_ldl_phys(cs, sm_state + 0x7f80); env->ldt.limit = x86_ldl_phys(cs, sm_state + 0x7f7c); env->ldt.flags = (x86_ldl_phys(cs, sm_state + 0x7f78) & 0xf0ff) << 8; env->gdt.base = x86_ldl_phys(cs, sm_state + 0x7f74); env->gdt.limit = x86_ldl_phys(cs, sm_state + 0x7f70); env->idt.base = x86_ldl_phys(cs, sm_state + 0x7f58); env->idt.limit = x86_ldl_phys(cs, sm_state + 0x7f54); for (i = 0; i < 6; i++) { if (i < 3) { offset = 0x7f84 + i * 12; } else { offset = 0x7f2c + (i - 3) * 12; } cpu_x86_load_seg_cache(env, i, x86_ldl_phys(cs, sm_state + 0x7fa8 + i * 4) & 0xffff, x86_ldl_phys(cs, sm_state + offset + 8), x86_ldl_phys(cs, sm_state + offset + 4), (x86_ldl_phys(cs, sm_state + offset) & 0xf0ff) << 8); } cpu_x86_update_cr4(env, x86_ldl_phys(cs, sm_state + 0x7f14)); val = x86_ldl_phys(cs, sm_state + 0x7efc); /* revision ID */ if (val & 0x20000) { env->smbase = x86_ldl_phys(cs, sm_state + 0x7ef8); } #endif if ((env->hflags2 & HF2_SMM_INSIDE_NMI_MASK) == 0) { env->hflags2 &= ~HF2_NMI_MASK; } env->hflags2 &= ~HF2_SMM_INSIDE_NMI_MASK; env->hflags &= ~HF_SMM_MASK; cpu_smm_update(cpu); qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n"); log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP); }