diff --git a/cpus.c b/cpus.c index 2b5c0bd7c7..eb1ac8577b 100644 --- a/cpus.c +++ b/cpus.c @@ -40,6 +40,7 @@ #include "qemu/bitmap.h" #include "qemu/seqlock.h" #include "qapi-event.h" +#include "hw/nmi.h" #ifndef _WIN32 #include "qemu/compatfd.h" @@ -1536,22 +1537,8 @@ void qmp_inject_nmi(Error **errp) apic_deliver_nmi(cpu->apic_state); } } -#elif defined(TARGET_S390X) - CPUState *cs; - S390CPU *cpu; - - CPU_FOREACH(cs) { - cpu = S390_CPU(cs); - if (cpu->env.cpu_num == monitor_get_cpu_index()) { - if (s390_cpu_restart(S390_CPU(cs)) == -1) { - error_set(errp, QERR_UNSUPPORTED); - return; - } - break; - } - } #else - error_set(errp, QERR_UNSUPPORTED); + nmi_monitor_handle(monitor_get_cpu_index(), errp); #endif } diff --git a/hmp-commands.hx b/hmp-commands.hx index d0943b1ff3..f859f8d29f 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -832,19 +832,17 @@ The values that can be specified here depend on the machine type, but are the same that can be specified in the @code{-boot} command line option. ETEXI -#if defined(TARGET_I386) || defined(TARGET_S390X) { .name = "nmi", .args_type = "", .params = "", - .help = "inject an NMI on all guest's CPUs", + .help = "inject an NMI", .mhandler.cmd = hmp_inject_nmi, }, -#endif STEXI @item nmi @var{cpu} @findex nmi -Inject an NMI (x86) or RESTART (s390x) on the given CPU. +Inject an NMI on the default CPU (x86/s390) or all CPUs (ppc64). ETEXI diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 5377d052e9..17845df3f0 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -4,6 +4,7 @@ common-obj-y += fw-path-provider.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o common-obj-y += hotplug.o +common-obj-y += nmi.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o diff --git a/hw/core/nmi.c b/hw/core/nmi.c new file mode 100644 index 0000000000..3dff020659 --- /dev/null +++ b/hw/core/nmi.c @@ -0,0 +1,84 @@ +/* + * NMI monitor handler class and helpers. + * + * Copyright IBM Corp., 2014 + * + * Author: Alexey Kardashevskiy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "hw/nmi.h" +#include "qapi/qmp/qerror.h" + +struct do_nmi_s { + int cpu_index; + Error *errp; + bool handled; +}; + +static void nmi_children(Object *o, struct do_nmi_s *ns); + +static int do_nmi(Object *o, void *opaque) +{ + struct do_nmi_s *ns = opaque; + NMIState *n = (NMIState *) object_dynamic_cast(o, TYPE_NMI); + + if (n) { + NMIClass *nc = NMI_GET_CLASS(n); + + ns->handled = true; + nc->nmi_monitor_handler(n, ns->cpu_index, &ns->errp); + if (ns->errp) { + return -1; + } + } + nmi_children(o, ns); + + return 0; +} + +static void nmi_children(Object *o, struct do_nmi_s *ns) +{ + object_child_foreach(o, do_nmi, ns); +} + +void nmi_monitor_handle(int cpu_index, Error **errp) +{ + struct do_nmi_s ns = { + .cpu_index = cpu_index, + .errp = NULL, + .handled = false + }; + + nmi_children(object_get_root(), &ns); + if (ns.handled) { + error_propagate(errp, ns.errp); + } else { + error_set(errp, QERR_UNSUPPORTED); + } +} + +static const TypeInfo nmi_info = { + .name = TYPE_NMI, + .parent = TYPE_INTERFACE, + .class_size = sizeof(NMIClass), +}; + +static void nmi_register_types(void) +{ + type_register_static(&nmi_info); +} + +type_init(nmi_register_types) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d01978f3dc..5cb452f234 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -55,6 +55,7 @@ #include "qemu/config-file.h" #include "qemu/error-report.h" #include "trace.h" +#include "hw/nmi.h" #include @@ -1576,10 +1577,28 @@ static void spapr_machine_initfn(Object *obj) spapr_get_kvm_type, spapr_set_kvm_type, NULL); } +static void ppc_cpu_do_nmi_on_cpu(void *arg) +{ + CPUState *cs = arg; + + cpu_synchronize_state(cs); + ppc_cpu_do_system_reset(cs); +} + +static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) +{ + CPUState *cs; + + CPU_FOREACH(cs) { + async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, cs); + } +} + static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); mc->name = "pseries"; mc->desc = "pSeries Logical Partition (PAPR compliant)"; @@ -1593,6 +1612,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->kvm_type = spapr_kvm_type; fwc->get_dev_path = spapr_get_fw_dev_path; + nc->nmi_monitor_handler = spapr_nmi; } static const TypeInfo spapr_machine_info = { @@ -1603,6 +1623,7 @@ static const TypeInfo spapr_machine_info = { .class_init = spapr_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_FW_PATH_PROVIDER }, + { TYPE_NMI }, { } }, }; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 42f5cec4c1..004b2c20c5 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -18,6 +18,8 @@ #include "css.h" #include "virtio-ccw.h" +#define TYPE_S390_CCW_MACHINE "s390-ccw-machine" + void io_subsystem_reset(void) { DeviceState *css, *sclp, *flic; @@ -134,24 +136,39 @@ static void ccw_init(MachineState *machine) s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); } -static QEMUMachine ccw_machine = { - .name = "s390-ccw-virtio", - .alias = "s390-ccw", - .desc = "VirtIO-ccw based S390 machine", - .init = ccw_init, - .block_default_type = IF_VIRTIO, - .no_cdrom = 1, - .no_floppy = 1, - .no_serial = 1, - .no_parallel = 1, - .no_sdcard = 1, - .use_sclp = 1, - .max_cpus = 255, -}; - -static void ccw_machine_init(void) +static void ccw_machine_class_init(ObjectClass *oc, void *data) { - qemu_register_machine(&ccw_machine); + MachineClass *mc = MACHINE_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); + + mc->name = "s390-ccw-virtio"; + mc->alias = "s390-ccw"; + mc->desc = "VirtIO-ccw based S390 machine"; + mc->init = ccw_init; + mc->block_default_type = IF_VIRTIO; + mc->no_cdrom = 1; + mc->no_floppy = 1; + mc->no_serial = 1; + mc->no_parallel = 1; + mc->no_sdcard = 1; + mc->use_sclp = 1, + mc->max_cpus = 255; + nc->nmi_monitor_handler = s390_nmi; } -machine_init(ccw_machine_init) +static const TypeInfo ccw_machine_info = { + .name = TYPE_S390_CCW_MACHINE, + .parent = TYPE_MACHINE, + .class_init = ccw_machine_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_NMI }, + { } + }, +}; + +static void ccw_machine_register_types(void) +{ + type_register_static(&ccw_machine_info); +} + +type_init(ccw_machine_register_types) diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 93c7acea72..1a75a1cf81 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -51,6 +51,7 @@ #define MAX_BLK_DEVS 10 #define ZIPL_FILENAME "s390-zipl.rom" +#define TYPE_S390_MACHINE "s390-machine" static VirtIOS390Bus *s390_bus; static S390CPU **ipi_states; @@ -279,25 +280,49 @@ static void s390_init(MachineState *machine) s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390"); } -static QEMUMachine s390_machine = { - .name = "s390-virtio", - .alias = "s390", - .desc = "VirtIO based S390 machine", - .init = s390_init, - .block_default_type = IF_VIRTIO, - .no_cdrom = 1, - .no_floppy = 1, - .no_serial = 1, - .no_parallel = 1, - .no_sdcard = 1, - .use_virtcon = 1, - .max_cpus = 255, - .is_default = 1, -}; - -static void s390_machine_init(void) +void s390_nmi(NMIState *n, int cpu_index, Error **errp) { - qemu_register_machine(&s390_machine); + CPUState *cs = qemu_get_cpu(cpu_index); + + if (s390_cpu_restart(S390_CPU(cs))) { + error_set(errp, QERR_UNSUPPORTED); + } } -machine_init(s390_machine_init); +static void s390_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); + + mc->name = "s390-virtio"; + mc->alias = "s390"; + mc->desc = "VirtIO based S390 machine"; + mc->init = s390_init; + mc->block_default_type = IF_VIRTIO; + mc->max_cpus = 255; + mc->no_serial = 1; + mc->no_parallel = 1; + mc->use_virtcon = 1; + mc->no_floppy = 1; + mc->no_cdrom = 1; + mc->no_sdcard = 1; + mc->is_default = 1; + nc->nmi_monitor_handler = s390_nmi; +} + +static const TypeInfo s390_machine_info = { + .name = TYPE_S390_MACHINE, + .parent = TYPE_MACHINE, + .class_init = s390_machine_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_NMI }, + { } + }, +}; + +static void s390_machine_register_types(void) +{ + type_register_static(&s390_machine_info); +} + +type_init(s390_machine_register_types) diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h index 5c405e7755..33847aefcf 100644 --- a/hw/s390x/s390-virtio.h +++ b/hw/s390x/s390-virtio.h @@ -12,6 +12,8 @@ #ifndef HW_S390_VIRTIO_H #define HW_S390_VIRTIO_H 1 +#include "hw/nmi.h" + #define KVM_S390_VIRTIO_NOTIFY 0 #define KVM_S390_VIRTIO_RESET 1 #define KVM_S390_VIRTIO_SET_STATUS 2 @@ -26,4 +28,5 @@ void s390_init_ipl_dev(const char *kernel_filename, const char *initrd_filename, const char *firmware); void s390_create_virtio_net(BusState *bus, const char *name); +void s390_nmi(NMIState *n, int cpu_index, Error **errp); #endif diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 233fc70d67..4df650f450 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -792,6 +792,7 @@ static void rtc_reset(void *opaque) #ifdef TARGET_I386 if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { s->irq_coalesced = 0; + s->irq_reinject_on_ack_count = 0; } #endif } diff --git a/include/hw/nmi.h b/include/hw/nmi.h new file mode 100644 index 0000000000..b541772e1d --- /dev/null +++ b/include/hw/nmi.h @@ -0,0 +1,49 @@ +/* + * NMI monitor handler class and helpers definitions. + * + * Copyright IBM Corp., 2014 + * + * Author: Alexey Kardashevskiy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef NMI_H +#define NMI_H 1 + +#include "qemu-common.h" +#include "qom/object.h" + +#define TYPE_NMI "nmi" + +#define NMI_CLASS(klass) \ + OBJECT_CLASS_CHECK(NMIClass, (klass), TYPE_NMI) +#define NMI_GET_CLASS(obj) \ + OBJECT_GET_CLASS(NMIClass, (obj), TYPE_NMI) +#define NMI(obj) \ + INTERFACE_CHECK(NMI, (obj), TYPE_NMI) + +typedef struct NMIState { + Object parent_obj; +} NMIState; + +typedef struct NMIClass { + InterfaceClass parent_class; + + void (*nmi_monitor_handler)(NMIState *n, int cpu_index, Error **errp); +} NMIClass; + +void nmi_monitor_handle(int cpu_index, Error **errp); + +#endif /* NMI_H */ diff --git a/kvm-all.c b/kvm-all.c index 1402f4f429..b240bf87a9 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1669,16 +1669,30 @@ void kvm_cpu_synchronize_state(CPUState *cpu) } } +static void do_kvm_cpu_synchronize_post_reset(void *arg) +{ + CPUState *cpu = arg; + + kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); + cpu->kvm_vcpu_dirty = false; +} + void kvm_cpu_synchronize_post_reset(CPUState *cpu) { - kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE); + run_on_cpu(cpu, do_kvm_cpu_synchronize_post_reset, cpu); +} + +static void do_kvm_cpu_synchronize_post_init(void *arg) +{ + CPUState *cpu = arg; + + kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); cpu->kvm_vcpu_dirty = false; } void kvm_cpu_synchronize_post_init(CPUState *cpu) { - kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE); - cpu->kvm_vcpu_dirty = false; + run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, cpu); } int kvm_cpu_exec(CPUState *cpu) diff --git a/qapi-schema.json b/qapi-schema.json index 341f417a5f..689b548abf 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1186,13 +1186,13 @@ ## # @inject-nmi: # -# Injects an Non-Maskable Interrupt into all guest's VCPUs. +# Injects a Non-Maskable Interrupt into the default CPU (x86/s390) or all CPUs (ppc64). # # Returns: If successful, nothing # # Since: 0.14.0 # -# Notes: Only x86 Virtual Machines support this command. +# Note: prior to 2.1, this command was only supported for x86 and s390 VMs ## { 'command': 'inject-nmi' } diff --git a/qmp-commands.hx b/qmp-commands.hx index 4be4765f27..7658d4bd24 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -477,7 +477,7 @@ SQMP inject-nmi ---------- -Inject an NMI on guest's CPUs. +Inject an NMI on the default CPU (x86/s390) or all CPUs (ppc64). Arguments: None. @@ -487,7 +487,6 @@ Example: <- { "return": {} } Note: inject-nmi fails when the guest doesn't support injecting. - Currently, only x86 (NMI) and s390x (RESTART) guests do. EQMP diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9d46e5a104..053e4320fc 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -206,9 +206,13 @@ our $UTF8 = qr { | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 }x; +# There are still some false positives, but this catches most +# common cases. our $typeTypedefs = qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t + [A-Z][A-Z\d_]*[a-z][A-Za-z\d_]* # camelcase + | [A-Z][A-Z\d_]*AIOCB # all uppercase + | [A-Z][A-Z\d_]*CPU # all uppercase + | QEMUBH # all uppercase )}; our $logFunctions = qr{(?x: diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 217500c735..fa811a02d1 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -257,8 +257,8 @@ static const char *svm_feature_name[] = { }; static const char *cpuid_7_0_ebx_feature_name[] = { - "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep", - "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL, + "fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep", + "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL, NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -2588,6 +2588,16 @@ static void x86_cpu_reset(CPUState *s) env->xcr0 = 1; + /* + * SDM 11.11.5 requires: + * - IA32_MTRR_DEF_TYPE MSR.E = 0 + * - IA32_MTRR_PHYSMASKn.V = 0 + * All other bits are undefined. For simplification, zero it all. + */ + env->mtrr_deftype = 0; + memset(env->mtrr_var, 0, sizeof(env->mtrr_var)); + memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); + #if !defined(CONFIG_USER_ONLY) /* We hard-wire the BSP to the first CPU. */ if (s->cpu_index == 0) { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e634d83e86..3460b12139 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -337,6 +337,8 @@ #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) +#define MSR_MTRRphysIndex(addr) ((((addr) & ~1u) - 0x200) / 2) + #define MSR_MTRRfix64K_00000 0x250 #define MSR_MTRRfix16K_80000 0x258 #define MSR_MTRRfix16K_A0000 0x259 @@ -930,7 +932,7 @@ typedef struct CPUX86State { /* MTRRs */ uint64_t mtrr_fixed[11]; uint64_t mtrr_deftype; - MTRRVar mtrr_var[8]; + MTRRVar mtrr_var[MSR_MTRRcap_VCNT]; /* For KVM */ uint32_t mp_state; diff --git a/target-i386/helper.c b/target-i386/helper.c index 47b982b437..30cb0d0143 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -615,8 +615,8 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, if (!(pdpe & PG_PRESENT_MASK)) { goto do_fault; } - rsvd_mask |= PG_HI_USER_MASK | PG_NX_MASK; - if (pdpe & rsvd_mask) { + rsvd_mask |= PG_HI_USER_MASK; + if (pdpe & (rsvd_mask | PG_NX_MASK)) { goto do_fault_rsvd; } ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 097fe1188d..ddedc735ff 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -79,6 +79,7 @@ static int lm_capable_kernel; static bool has_msr_hv_hypercall; static bool has_msr_hv_vapic; static bool has_msr_hv_tsc; +static bool has_msr_mtrr; static bool has_msr_architectural_pmu; static uint32_t num_architectural_pmu_counters; @@ -739,6 +740,10 @@ int kvm_arch_init_vcpu(CPUState *cs) env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); } + if (env->features[FEAT_1_EDX] & CPUID_MTRR) { + has_msr_mtrr = true; + } + return 0; } @@ -1183,7 +1188,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) CPUX86State *env = &cpu->env; struct { struct kvm_msrs info; - struct kvm_msr_entry entries[100]; + struct kvm_msr_entry entries[150]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; int n = 0, i; @@ -1278,6 +1283,37 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_REFERENCE_TSC, env->msr_hv_tsc); } + if (has_msr_mtrr) { + kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix64K_00000, env->mtrr_fixed[0]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix16K_80000, env->mtrr_fixed[1]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]); + for (i = 0; i < MSR_MTRRcap_VCNT; i++) { + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRphysBase(i), env->mtrr_var[i].base); + kvm_msr_entry_set(&msrs[n++], + MSR_MTRRphysMask(i), env->mtrr_var[i].mask); + } + } /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see * kvm_put_msr_feature_control. */ @@ -1484,7 +1520,7 @@ static int kvm_get_msrs(X86CPU *cpu) CPUX86State *env = &cpu->env; struct { struct kvm_msrs info; - struct kvm_msr_entry entries[100]; + struct kvm_msr_entry entries[150]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; int ret, i, n; @@ -1572,6 +1608,24 @@ static int kvm_get_msrs(X86CPU *cpu) if (has_msr_hv_tsc) { msrs[n++].index = HV_X64_MSR_REFERENCE_TSC; } + if (has_msr_mtrr) { + msrs[n++].index = MSR_MTRRdefType; + msrs[n++].index = MSR_MTRRfix64K_00000; + msrs[n++].index = MSR_MTRRfix16K_80000; + msrs[n++].index = MSR_MTRRfix16K_A0000; + msrs[n++].index = MSR_MTRRfix4K_C0000; + msrs[n++].index = MSR_MTRRfix4K_C8000; + msrs[n++].index = MSR_MTRRfix4K_D0000; + msrs[n++].index = MSR_MTRRfix4K_D8000; + msrs[n++].index = MSR_MTRRfix4K_E0000; + msrs[n++].index = MSR_MTRRfix4K_E8000; + msrs[n++].index = MSR_MTRRfix4K_F0000; + msrs[n++].index = MSR_MTRRfix4K_F8000; + for (i = 0; i < MSR_MTRRcap_VCNT; i++) { + msrs[n++].index = MSR_MTRRphysBase(i); + msrs[n++].index = MSR_MTRRphysMask(i); + } + } msr_data.info.nmsrs = n; ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); @@ -1692,6 +1746,49 @@ static int kvm_get_msrs(X86CPU *cpu) case HV_X64_MSR_REFERENCE_TSC: env->msr_hv_tsc = msrs[i].data; break; + case MSR_MTRRdefType: + env->mtrr_deftype = msrs[i].data; + break; + case MSR_MTRRfix64K_00000: + env->mtrr_fixed[0] = msrs[i].data; + break; + case MSR_MTRRfix16K_80000: + env->mtrr_fixed[1] = msrs[i].data; + break; + case MSR_MTRRfix16K_A0000: + env->mtrr_fixed[2] = msrs[i].data; + break; + case MSR_MTRRfix4K_C0000: + env->mtrr_fixed[3] = msrs[i].data; + break; + case MSR_MTRRfix4K_C8000: + env->mtrr_fixed[4] = msrs[i].data; + break; + case MSR_MTRRfix4K_D0000: + env->mtrr_fixed[5] = msrs[i].data; + break; + case MSR_MTRRfix4K_D8000: + env->mtrr_fixed[6] = msrs[i].data; + break; + case MSR_MTRRfix4K_E0000: + env->mtrr_fixed[7] = msrs[i].data; + break; + case MSR_MTRRfix4K_E8000: + env->mtrr_fixed[8] = msrs[i].data; + break; + case MSR_MTRRfix4K_F0000: + env->mtrr_fixed[9] = msrs[i].data; + break; + case MSR_MTRRfix4K_F8000: + env->mtrr_fixed[10] = msrs[i].data; + break; + case MSR_MTRRphysBase(0) ... MSR_MTRRphysMask(MSR_MTRRcap_VCNT - 1): + if (index & 1) { + env->mtrr_var[MSR_MTRRphysIndex(index)].mask = msrs[i].data; + } else { + env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data; + } + break; } } diff --git a/target-i386/machine.c b/target-i386/machine.c index 16d2f6a809..fb890654b1 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -677,7 +677,7 @@ VMStateDescription vmstate_x86_cpu = { /* MTRRs */ VMSTATE_UINT64_ARRAY_V(env.mtrr_fixed, X86CPU, 11, 8), VMSTATE_UINT64_V(env.mtrr_deftype, X86CPU, 8), - VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, 8, 8), + VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, MSR_MTRRcap_VCNT, 8), /* KVM-related states */ VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9), VMSTATE_UINT32_V(env.mp_state, X86CPU, 9), diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index 0fee36f06a..a379f795bc 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -127,6 +127,7 @@ int ppc64_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); #ifndef CONFIG_USER_ONLY +void ppc_cpu_do_system_reset(CPUState *cs); extern const struct VMStateDescription vmstate_ppc_cpu; typedef struct PPCTimebase { diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index be7159013f..922e86d54b 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -810,6 +810,14 @@ void ppc_hw_interrupt(CPUPPCState *env) } } } + +void ppc_cpu_do_system_reset(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); +} #endif /* !CONFIG_USER_ONLY */ #if defined(DEBUG_OP) diff --git a/vl.c b/vl.c index b796c67e9d..95be92d6fe 100644 --- a/vl.c +++ b/vl.c @@ -4033,11 +4033,6 @@ int main(int argc, char **argv, char **envp) qemu_set_version(machine_class->hw_version); } - if (qemu_opts_foreach(qemu_find_opts("object"), - object_create, NULL, 0) != 0) { - exit(1); - } - /* Init CPU def lists, based on config * - Must be called after all the qemu_read_config_file() calls * - Must be called before list_cpus() @@ -4249,6 +4244,11 @@ int main(int argc, char **argv, char **envp) exit(0); } + if (qemu_opts_foreach(qemu_find_opts("object"), + object_create, NULL, 0) != 0) { + exit(1); + } + machine_opts = qemu_get_machine_opts(); if (qemu_opt_foreach(machine_opts, object_set_property, current_machine, 1) < 0) {