void helper_debug(CPUX86State *env) { CPUState *cs = CPU(x86_env_get_cpu(env)); cs->exception_index = EXCP_DEBUG; cpu_loop_exit(cs); }
void helper_invlpg(CPUX86State *env, target_ulong addr) { X86CPU *cpu = x86_env_get_cpu(env); cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC()); tlb_flush_page(CPU(cpu), addr); }
void helper_pause(CPUX86State *env, int next_eip_addend) { X86CPU *cpu = x86_env_get_cpu(env); cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC()); env->eip += next_eip_addend; do_pause(cpu); }
void helper_hlt(CPUX86State *env, int next_eip_addend) { X86CPU *cpu = x86_env_get_cpu(env); cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0); env->eip += next_eip_addend; do_hlt(cpu); }
void helper_wrpkru(CPUX86State *env, uint32_t ecx, uint64_t val) { CPUState *cs = CPU(x86_env_get_cpu(env)); if ((env->cr[4] & CR4_PKE_MASK) == 0) { raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC()); } if (ecx != 0 || (val & 0xFFFFFFFF00000000ull)) { raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC()); } env->pkru = val; tlb_flush(cs); }
target_ulong helper_read_crN(CPUX86State *env, int reg) { target_ulong val; cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC()); switch (reg) { default: val = env->cr[reg]; break; case 8: if (!(env->hflags2 & HF2_VINTR_MASK)) { val = cpu_get_apic_tpr(x86_env_get_cpu(env)->apic_state); } else { val = env->v_tpr; } break; } return val; }
/* * Signal an interruption. It is executed in the main CPU loop. * is_int is TRUE if coming from the int instruction. next_eip is the * env->eip value AFTER the interrupt instruction. It is only relevant if * is_int is TRUE. */ static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno, int is_int, int error_code, int next_eip_addend) { CPUState *cs = CPU(x86_env_get_cpu(env)); if (!is_int) { cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno, error_code); intno = check_exception(env, intno, &error_code); } else { cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0); } cs->exception_index = intno; // qq env->error_code = error_code; env->exception_is_int = is_int; env->exception_next_eip = env->eip + next_eip_addend; cpu_loop_exit(cs); }
void helper_mwait(CPUX86State *env, int next_eip_addend) { CPUState *cs; X86CPU *cpu; if ((uint32_t)env->regs[R_ECX] != 0) { raise_exception_ra(env, EXCP0D_GPF, GETPC()); } cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC()); env->eip += next_eip_addend; cpu = x86_env_get_cpu(env); cs = CPU(cpu); /* XXX: not complete but not completely erroneous */ if (cs->cpu_index != 0 || CPU_NEXT(cs) != NULL) { do_pause(cpu); } else { do_hlt(cpu); } }
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; } }
static void apic_reset_common(DeviceState *d) { APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); bool bsp; bsp = cpu_is_bsp(x86_env_get_cpu(s->cpu_env)); s->apicbase = 0xfee00000 | (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; s->vapic_paddr = 0; info->vapic_base_update(s); apic_init_reset(d); if (bsp) { /* * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization * time typically by BIOS, so PIC interrupt can be delivered to the * processor when local APIC is enabled. */ s->lvt[APIC_LVT_LINT0] = 0x700; } }
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); }
/* PC hardware initialisation */ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *system_io, ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model, int pci_enabled, int kvmclock_enabled) { int i; ram_addr_t below_4g_mem_size, above_4g_mem_size; PCIBus *pci_bus; ISABus *isa_bus; PCII440FXState *i440fx_state; int piix3_devfn = -1; qemu_irq *cpu_irq; qemu_irq *gsi; qemu_irq *i8259; qemu_irq *smi_irq; GSIState *gsi_state; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BusState *idebus[MAX_IDE_BUS]; ISADevice *rtc_state; ISADevice *floppy; MemoryRegion *ram_memory; MemoryRegion *pci_memory; MemoryRegion *rom_memory; void *fw_cfg = NULL; pc_cpus_init(cpu_model); pc_acpi_init("acpi-dsdt.aml"); if (kvmclock_enabled) { kvmclock_create(); } if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; below_4g_mem_size = 0xe0000000; } else { above_4g_mem_size = 0; below_4g_mem_size = ram_size; } if (pci_enabled) { pci_memory = g_new(MemoryRegion, 1); memory_region_init(pci_memory, "pci", INT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; rom_memory = system_memory; } /* allocate ram and load rom/bios */ if (!xen_enabled()) { fw_cfg = pc_memory_init(system_memory, kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, rom_memory, &ram_memory); } gsi_state = g_malloc0(sizeof(*gsi_state)); if (kvm_irqchip_in_kernel()) { kvm_pc_setup_irq_routing(pci_enabled); gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state, GSI_NUM_PINS); } else { gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS); } if (pci_enabled) { pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, system_memory, system_io, ram_size, below_4g_mem_size, 0x100000000ULL - below_4g_mem_size, 0x100000000ULL + above_4g_mem_size, (sizeof(hwaddr) == 4 ? 0 : ((uint64_t)1 << 62)), pci_memory, ram_memory); } else { pci_bus = NULL; i440fx_state = NULL; isa_bus = isa_bus_new(NULL, system_io); no_hpet = 1; } isa_bus_irqs(isa_bus, gsi); if (kvm_irqchip_in_kernel()) { i8259 = kvm_i8259_init(isa_bus); } else if (xen_enabled()) { i8259 = xen_interrupt_controller_init(); } else { cpu_irq = pc_allocate_cpu_irq(); i8259 = i8259_init(isa_bus, cpu_irq[0]); } for (i = 0; i < ISA_NUM_IRQS; i++) { gsi_state->i8259_irq[i] = i8259[i]; } if (pci_enabled) { ioapic_init_gsi(gsi_state, "i440fx"); } pc_register_ferr_irq(gsi[13]); pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL); if (xen_enabled()) { pci_create_simple(pci_bus, -1, "xen-platform"); } /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled()); pc_nic_init(isa_bus, pci_bus); ide_drive_get(hd, MAX_IDE_BUS); if (pci_enabled) { PCIDevice *dev; if (xen_enabled()) { dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1); } else { dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); } idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); } else { for(i = 0; i < MAX_IDE_BUS; i++) { ISADevice *dev; dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0"); } } audio_init(isa_bus, pci_enabled ? pci_bus : NULL); pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, floppy, idebus[0], idebus[1], rtc_state); if (pci_enabled && usb_enabled(false)) { pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); } if (pci_enabled && acpi_enabled) { i2c_bus *smbus; smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, x86_env_get_cpu(first_cpu), 1); /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, kvm_enabled(), fw_cfg); smbus_eeprom_init(smbus, 8, NULL, 0); } if (pci_enabled) { pc_pci_device_init(pci_bus); } }
void helper_rdmsr(CPUX86State *env) { uint64_t val; cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC()); switch ((uint32_t)env->regs[R_ECX]) { case MSR_IA32_SYSENTER_CS: val = env->sysenter_cs; break; case MSR_IA32_SYSENTER_ESP: val = env->sysenter_esp; break; case MSR_IA32_SYSENTER_EIP: val = env->sysenter_eip; break; case MSR_IA32_APICBASE: val = cpu_get_apic_base(x86_env_get_cpu(env)->apic_state); break; case MSR_EFER: val = env->efer; break; case MSR_STAR: val = env->star; break; case MSR_PAT: val = env->pat; break; case MSR_VM_HSAVE_PA: val = env->vm_hsave; break; case MSR_IA32_PERF_STATUS: /* tsc_increment_by_tick */ val = 1000ULL; /* CPU multiplier */ val |= (((uint64_t)4ULL) << 40); break; #ifdef TARGET_X86_64 case MSR_LSTAR: val = env->lstar; break; case MSR_CSTAR: val = env->cstar; break; case MSR_FMASK: val = env->fmask; break; case MSR_FSBASE: val = env->segs[R_FS].base; break; case MSR_GSBASE: val = env->segs[R_GS].base; break; case MSR_KERNELGSBASE: val = env->kernelgsbase; break; case MSR_TSC_AUX: val = env->tsc_aux; break; #endif case MSR_MTRRphysBase(0): case MSR_MTRRphysBase(1): case MSR_MTRRphysBase(2): case MSR_MTRRphysBase(3): case MSR_MTRRphysBase(4): case MSR_MTRRphysBase(5): case MSR_MTRRphysBase(6): case MSR_MTRRphysBase(7): val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - MSR_MTRRphysBase(0)) / 2].base; break; case MSR_MTRRphysMask(0): case MSR_MTRRphysMask(1): case MSR_MTRRphysMask(2): case MSR_MTRRphysMask(3): case MSR_MTRRphysMask(4): case MSR_MTRRphysMask(5): case MSR_MTRRphysMask(6): case MSR_MTRRphysMask(7): val = env->mtrr_var[((uint32_t)env->regs[R_ECX] - MSR_MTRRphysMask(0)) / 2].mask; break; case MSR_MTRRfix64K_00000: val = env->mtrr_fixed[0]; break; case MSR_MTRRfix16K_80000: case MSR_MTRRfix16K_A0000: val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix16K_80000 + 1]; break; case MSR_MTRRfix4K_C0000: case MSR_MTRRfix4K_C8000: case MSR_MTRRfix4K_D0000: case MSR_MTRRfix4K_D8000: case MSR_MTRRfix4K_E0000: case MSR_MTRRfix4K_E8000: case MSR_MTRRfix4K_F0000: case MSR_MTRRfix4K_F8000: val = env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix4K_C0000 + 3]; break; case MSR_MTRRdefType: val = env->mtrr_deftype; break; case MSR_MTRRcap: if (env->features[FEAT_1_EDX] & CPUID_MTRR) { val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED; } else { /* XXX: exception? */ val = 0; } break; case MSR_MCG_CAP: val = env->mcg_cap; break; case MSR_MCG_CTL: if (env->mcg_cap & MCG_CTL_P) { val = env->mcg_ctl; } else { val = 0; } break; case MSR_MCG_STATUS: val = env->mcg_status; break; case MSR_IA32_MISC_ENABLE: val = env->msr_ia32_misc_enable; break; case MSR_IA32_BNDCFGS: val = env->msr_bndcfgs; break; default: if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) { uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; val = env->mce_banks[offset]; break; } /* XXX: exception? */ val = 0; break; } env->regs[R_EAX] = (uint32_t)(val); env->regs[R_EDX] = (uint32_t)(val >> 32); }
void helper_wrmsr(CPUX86State *env) { uint64_t val; cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC()); val = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); switch ((uint32_t)env->regs[R_ECX]) { case MSR_IA32_SYSENTER_CS: env->sysenter_cs = val & 0xffff; break; case MSR_IA32_SYSENTER_ESP: env->sysenter_esp = val; break; case MSR_IA32_SYSENTER_EIP: env->sysenter_eip = val; break; case MSR_IA32_APICBASE: cpu_set_apic_base(x86_env_get_cpu(env)->apic_state, val); break; case MSR_EFER: { uint64_t update_mask; update_mask = 0; if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { update_mask |= MSR_EFER_SCE; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { update_mask |= MSR_EFER_LME; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { update_mask |= MSR_EFER_FFXSR; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { update_mask |= MSR_EFER_NXE; } if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { update_mask |= MSR_EFER_SVME; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { update_mask |= MSR_EFER_FFXSR; } cpu_load_efer(env, (env->efer & ~update_mask) | (val & update_mask)); } break; case MSR_STAR: env->star = val; break; case MSR_PAT: env->pat = val; break; case MSR_VM_HSAVE_PA: env->vm_hsave = val; break; #ifdef TARGET_X86_64 case MSR_LSTAR: env->lstar = val; break; case MSR_CSTAR: env->cstar = val; break; case MSR_FMASK: env->fmask = val; break; case MSR_FSBASE: env->segs[R_FS].base = val; break; case MSR_GSBASE: env->segs[R_GS].base = val; break; case MSR_KERNELGSBASE: env->kernelgsbase = val; break; #endif case MSR_MTRRphysBase(0): case MSR_MTRRphysBase(1): case MSR_MTRRphysBase(2): case MSR_MTRRphysBase(3): case MSR_MTRRphysBase(4): case MSR_MTRRphysBase(5): case MSR_MTRRphysBase(6): case MSR_MTRRphysBase(7): env->mtrr_var[((uint32_t)env->regs[R_ECX] - MSR_MTRRphysBase(0)) / 2].base = val; break; case MSR_MTRRphysMask(0): case MSR_MTRRphysMask(1): case MSR_MTRRphysMask(2): case MSR_MTRRphysMask(3): case MSR_MTRRphysMask(4): case MSR_MTRRphysMask(5): case MSR_MTRRphysMask(6): case MSR_MTRRphysMask(7): env->mtrr_var[((uint32_t)env->regs[R_ECX] - MSR_MTRRphysMask(0)) / 2].mask = val; break; case MSR_MTRRfix64K_00000: env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix64K_00000] = val; break; case MSR_MTRRfix16K_80000: case MSR_MTRRfix16K_A0000: env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix16K_80000 + 1] = val; break; case MSR_MTRRfix4K_C0000: case MSR_MTRRfix4K_C8000: case MSR_MTRRfix4K_D0000: case MSR_MTRRfix4K_D8000: case MSR_MTRRfix4K_E0000: case MSR_MTRRfix4K_E8000: case MSR_MTRRfix4K_F0000: case MSR_MTRRfix4K_F8000: env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix4K_C0000 + 3] = val; break; case MSR_MTRRdefType: env->mtrr_deftype = val; break; case MSR_MCG_STATUS: env->mcg_status = val; break; case MSR_MCG_CTL: if ((env->mcg_cap & MCG_CTL_P) && (val == 0 || val == ~(uint64_t)0)) { env->mcg_ctl = val; } break; case MSR_TSC_AUX: env->tsc_aux = val; break; case MSR_IA32_MISC_ENABLE: env->msr_ia32_misc_enable = val; break; case MSR_IA32_BNDCFGS: /* FIXME: #GP if reserved bits are set. */ /* FIXME: Extend highest implemented bit of linear address. */ env->msr_bndcfgs = val; cpu_sync_bndcs_hflags(env); break; default: if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) { uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; if ((offset & 0x3) != 0 || (val == 0 || val == ~(uint64_t)0)) { env->mce_banks[offset] = val; } break; } /* XXX: exception? */ break; } }