void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) { cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC()); switch (reg) { case 0: cpu_x86_update_cr0(env, t0); break; case 3: cpu_x86_update_cr3(env, t0); break; case 4: cpu_x86_update_cr4(env, t0); break; case 8: if (!(env->hflags2 & HF2_VINTR_MASK)) { cpu_set_apic_tpr(x86_env_get_cpu(env)->apic_state, t0); } env->v_tpr = t0 & 0x0f; break; default: env->cr[reg] = t0; break; } }
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); }
void helper_rsm(CPUX86State *env) { target_ulong sm_state; int i, offset; uint32_t val; sm_state = env->smbase + 0x8000; #ifdef TARGET_X86_64 cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0)); for(i = 0; i < 6; i++) { offset = 0x7e00 + i * 16; cpu_x86_load_seg_cache(env, i, lduw_phys(sm_state + offset), ldq_phys(sm_state + offset + 8), ldl_phys(sm_state + offset + 4), (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8); } env->gdt.base = ldq_phys(sm_state + 0x7e68); env->gdt.limit = ldl_phys(sm_state + 0x7e64); env->ldt.selector = lduw_phys(sm_state + 0x7e70); env->ldt.base = ldq_phys(sm_state + 0x7e78); env->ldt.limit = ldl_phys(sm_state + 0x7e74); env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8; env->idt.base = ldq_phys(sm_state + 0x7e88); env->idt.limit = ldl_phys(sm_state + 0x7e84); env->tr.selector = lduw_phys(sm_state + 0x7e90); env->tr.base = ldq_phys(sm_state + 0x7e98); env->tr.limit = ldl_phys(sm_state + 0x7e94); env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8; EAX = ldq_phys(sm_state + 0x7ff8); ECX = ldq_phys(sm_state + 0x7ff0); EDX = ldq_phys(sm_state + 0x7fe8); EBX = ldq_phys(sm_state + 0x7fe0); ESP = ldq_phys(sm_state + 0x7fd8); EBP = ldq_phys(sm_state + 0x7fd0); ESI = ldq_phys(sm_state + 0x7fc8); EDI = ldq_phys(sm_state + 0x7fc0); for(i = 8; i < 16; i++) env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8); env->eip = ldq_phys(sm_state + 0x7f78); cpu_load_eflags(env, ldl_phys(sm_state + 0x7f70), ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); env->dr[6] = ldl_phys(sm_state + 0x7f68); env->dr[7] = ldl_phys(sm_state + 0x7f60); cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48)); cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50)); cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58)); val = ldl_phys(sm_state + 0x7efc); /* revision ID */ if (val & 0x20000) { env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff; } #else cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc)); cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8)); cpu_load_eflags(env, ldl_phys(sm_state + 0x7ff4), ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); env->eip = ldl_phys(sm_state + 0x7ff0); EDI = ldl_phys(sm_state + 0x7fec); ESI = ldl_phys(sm_state + 0x7fe8); EBP = ldl_phys(sm_state + 0x7fe4); ESP = ldl_phys(sm_state + 0x7fe0); EBX = ldl_phys(sm_state + 0x7fdc); EDX = ldl_phys(sm_state + 0x7fd8); ECX = ldl_phys(sm_state + 0x7fd4); EAX = ldl_phys(sm_state + 0x7fd0); env->dr[6] = ldl_phys(sm_state + 0x7fcc); env->dr[7] = ldl_phys(sm_state + 0x7fc8); env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff; env->tr.base = ldl_phys(sm_state + 0x7f64); env->tr.limit = ldl_phys(sm_state + 0x7f60); env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8; env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff; env->ldt.base = ldl_phys(sm_state + 0x7f80); env->ldt.limit = ldl_phys(sm_state + 0x7f7c); env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8; env->gdt.base = ldl_phys(sm_state + 0x7f74); env->gdt.limit = ldl_phys(sm_state + 0x7f70); env->idt.base = ldl_phys(sm_state + 0x7f58); env->idt.limit = ldl_phys(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, ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff, ldl_phys(sm_state + offset + 8), ldl_phys(sm_state + offset + 4), (ldl_phys(sm_state + offset) & 0xf0ff) << 8); } cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14)); val = ldl_phys(sm_state + 0x7efc); /* revision ID */ if (val & 0x20000) { env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff; } #endif CC_OP = CC_OP_EFLAGS; env->hflags &= ~HF_SMM_MASK; cpu_smm_update(env); qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n"); log_cpu_state_mask(CPU_LOG_INT, ENV_GET_CPU(env), X86_DUMP_CCOP); }