diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-03-19 18:01:17 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-03-19 18:01:17 +0000 |
commit | bdee969c0e65d4d509932b1d70e3a3b2ffbff6d5 (patch) | |
tree | 188cc6a895d8775cfc80467bce7590a9da408755 /target/i386 | |
parent | 2e1293cbaac75e84f541f9acfa8e26749f4c3562 (diff) | |
parent | af05ffffd7fa28010d4df9f5744514b16e71055d (diff) |
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging
* fixes for i386 TCG paging
* fixes for Hyper-V enlightenments
* avoid uninitialized variable warning
# gpg: Signature made Fri 19 Mar 2021 14:38:12 GMT
# gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83
# gpg: issuer "pbonzini@redhat.com"
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini-gitlab/tags/for-upstream:
tests/qtest: cleanup the testcase for bug 1878642
hw/intc/i8259: Refactor pic_read_irq() to avoid uninitialized variable
i386: Make migration fail when Hyper-V reenlightenment was enabled but 'user_tsc_khz' is unset
i386: Fix 'hypercall_hypercall' typo
target/i386: svm: do not discard high 32 bits of EXITINFO1
target/i386: fail if toggling LA57 in 64-bit mode
target/i386: allow modifying TCG phys-addr-bits
qom: use qemu_printf to print help for user-creatable objects
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/i386')
-rw-r--r-- | target/i386/cpu.c | 23 | ||||
-rw-r--r-- | target/i386/cpu.h | 1 | ||||
-rw-r--r-- | target/i386/kvm/hyperv-proto.h | 1 | ||||
-rw-r--r-- | target/i386/machine.c | 24 | ||||
-rw-r--r-- | target/i386/tcg/excp_helper.c | 7 | ||||
-rw-r--r-- | target/i386/tcg/helper-tcg.h | 14 | ||||
-rw-r--r-- | target/i386/tcg/misc_helper.c | 4 | ||||
-rw-r--r-- | target/i386/tcg/seg_helper.c | 4 | ||||
-rw-r--r-- | target/i386/tcg/svm_helper.c | 15 |
9 files changed, 53 insertions, 40 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ae9fd9f31d..6b3e9467f1 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6785,21 +6785,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) cpu->phys_bits = cpu->host_phys_bits_limit; } } - - if (cpu->phys_bits && - (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS || - cpu->phys_bits < 32)) { - error_setg(errp, "phys-bits should be between 32 and %u " - " (but is %u)", - TARGET_PHYS_ADDR_SPACE_BITS, cpu->phys_bits); - return; - } - } else { - if (cpu->phys_bits && cpu->phys_bits != TCG_PHYS_ADDR_BITS) { - error_setg(errp, "TCG only supports phys-bits=%u", - TCG_PHYS_ADDR_BITS); - return; - } + } + if (cpu->phys_bits && + (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS || + cpu->phys_bits < 32)) { + error_setg(errp, "phys-bits should be between 32 and %u " + " (but is %u)", + TARGET_PHYS_ADDR_SPACE_BITS, cpu->phys_bits); + return; } /* 0 means it was not explicitly set by the user (or by machine * compat_props or by the host code above). In this case, the default diff --git a/target/i386/cpu.h b/target/i386/cpu.h index b4b136cd0d..570f916878 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -290,7 +290,6 @@ typedef enum X86Seg { #define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) #define PG_PSE_PAT_MASK (1 << PG_PSE_PAT_BIT) #define PG_ADDRESS_MASK 0x000ffffffffff000LL -#define PG_HI_RSVD_MASK (PG_ADDRESS_MASK & ~PHYS_ADDR_MASK) #define PG_HI_USER_MASK 0x7ff0000000000000LL #define PG_PKRU_MASK (15ULL << PG_PKRU_BIT) #define PG_NX_MASK (1ULL << PG_NX_BIT) diff --git a/target/i386/kvm/hyperv-proto.h b/target/i386/kvm/hyperv-proto.h index 056a305be3..e30d64b4ad 100644 --- a/target/i386/kvm/hyperv-proto.h +++ b/target/i386/kvm/hyperv-proto.h @@ -139,6 +139,7 @@ * Reenlightenment notification MSRs */ #define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106 +#define HV_REENLIGHTENMENT_ENABLE_BIT (1u << 16) #define HV_X64_MSR_TSC_EMULATION_CONTROL 0x40000107 #define HV_X64_MSR_TSC_EMULATION_STATUS 0x40000108 diff --git a/target/i386/machine.c b/target/i386/machine.c index 3967dfc257..137604ddb8 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -705,7 +705,7 @@ static bool hyperv_hypercall_enable_needed(void *opaque) return env->msr_hv_hypercall != 0 || env->msr_hv_guest_os_id != 0; } -static const VMStateDescription vmstate_msr_hypercall_hypercall = { +static const VMStateDescription vmstate_msr_hyperv_hypercall = { .name = "cpu/msr_hyperv_hypercall", .version_id = 1, .minimum_version_id = 1, @@ -883,11 +883,31 @@ static bool hyperv_reenlightenment_enable_needed(void *opaque) env->msr_hv_tsc_emulation_status != 0; } +static int hyperv_reenlightenment_post_load(void *opaque, int version_id) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + /* + * KVM doesn't fully support re-enlightenment notifications so we need to + * make sure TSC frequency doesn't change upon migration. + */ + if ((env->msr_hv_reenlightenment_control & HV_REENLIGHTENMENT_ENABLE_BIT) && + !env->user_tsc_khz) { + error_report("Guest enabled re-enlightenment notifications, " + "'tsc-frequency=' has to be specified"); + return -EINVAL; + } + + return 0; +} + static const VMStateDescription vmstate_msr_hyperv_reenlightenment = { .name = "cpu/msr_hyperv_reenlightenment", .version_id = 1, .minimum_version_id = 1, .needed = hyperv_reenlightenment_enable_needed, + .post_load = hyperv_reenlightenment_post_load, .fields = (VMStateField[]) { VMSTATE_UINT64(env.msr_hv_reenlightenment_control, X86CPU), VMSTATE_UINT64(env.msr_hv_tsc_emulation_control, X86CPU), @@ -1484,7 +1504,7 @@ VMStateDescription vmstate_x86_cpu = { &vmstate_msr_ia32_feature_control, &vmstate_msr_architectural_pmu, &vmstate_mpx, - &vmstate_msr_hypercall_hypercall, + &vmstate_msr_hyperv_hypercall, &vmstate_msr_hyperv_vapic, &vmstate_msr_hyperv_time, &vmstate_msr_hyperv_crash, diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c index b7d6259e4a..1e71e44510 100644 --- a/target/i386/tcg/excp_helper.c +++ b/target/i386/tcg/excp_helper.c @@ -142,8 +142,9 @@ void raise_exception_ra(CPUX86State *env, int exception_index, uintptr_t retaddr static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type, int *prot) { - CPUX86State *env = &X86_CPU(cs)->env; - uint64_t rsvd_mask = PG_HI_RSVD_MASK; + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; + uint64_t rsvd_mask = PG_ADDRESS_MASK & ~MAKE_64BIT_MASK(0, cpu->phys_bits); uint64_t ptep, pte; uint64_t exit_info_1 = 0; target_ulong pde_addr, pte_addr; @@ -358,7 +359,7 @@ static int handle_mmu_fault(CPUState *cs, vaddr addr, int size, int error_code = 0; int is_dirty, prot, page_size, is_write, is_user; hwaddr paddr; - uint64_t rsvd_mask = PG_HI_RSVD_MASK; + uint64_t rsvd_mask = PG_ADDRESS_MASK & ~MAKE_64BIT_MASK(0, cpu->phys_bits); uint32_t page_offset; target_ulong vaddr; uint32_t pkr; diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index c133c63555..bcdfca06f6 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -25,17 +25,13 @@ /* Maximum instruction code size */ #define TARGET_MAX_INSN_SIZE 16 -/* - * XXX: This value should match the one returned by CPUID - * and in exec.c - */ -# if defined(TARGET_X86_64) +#if defined(TARGET_X86_64) # define TCG_PHYS_ADDR_BITS 40 -# else +#else # define TCG_PHYS_ADDR_BITS 36 -# endif +#endif -#define PHYS_ADDR_MASK MAKE_64BIT_MASK(0, TCG_PHYS_ADDR_BITS) +QEMU_BUILD_BUG_ON(TCG_PHYS_ADDR_BITS > TARGET_PHYS_ADDR_SPACE_BITS); /** * x86_cpu_do_interrupt: @@ -84,7 +80,7 @@ void cpu_load_eflags(CPUX86State *env, int eflags, int update_mask); /* svm_helper.c */ void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr); -void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1); +void do_vmexit(CPUX86State *env); /* seg_helper.c */ void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); diff --git a/target/i386/tcg/misc_helper.c b/target/i386/tcg/misc_helper.c index 90b87fdef0..a25428c36e 100644 --- a/target/i386/tcg/misc_helper.c +++ b/target/i386/tcg/misc_helper.c @@ -167,6 +167,10 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0) cpu_x86_update_cr3(env, t0); break; case 4: + if (((t0 ^ env->cr[4]) & CR4_LA57_MASK) && + (env->hflags & HF_CS64_MASK)) { + raise_exception_ra(env, EXCP0D_GPF, GETPC()); + } cpu_x86_update_cr4(env, t0); break; case 8: diff --git a/target/i386/tcg/seg_helper.c b/target/i386/tcg/seg_helper.c index 180d47f0e9..d180a381d1 100644 --- a/target/i386/tcg/seg_helper.c +++ b/target/i386/tcg/seg_helper.c @@ -1305,9 +1305,9 @@ void x86_cpu_do_interrupt(CPUState *cs) /* successfully delivered */ env->old_exception = -1; #else - if (cs->exception_index >= EXCP_VMEXIT) { + if (cs->exception_index == EXCP_VMEXIT) { assert(env->old_exception == -1); - do_vmexit(env, cs->exception_index - EXCP_VMEXIT, env->error_code); + do_vmexit(env); } else { do_interrupt_all(cpu, cs->exception_index, env->exception_is_int, diff --git a/target/i386/tcg/svm_helper.c b/target/i386/tcg/svm_helper.c index 097bb9b83d..0145afceae 100644 --- a/target/i386/tcg/svm_helper.c +++ b/target/i386/tcg/svm_helper.c @@ -621,15 +621,19 @@ void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1, control.exit_info_2)), env->eip); - cs->exception_index = EXCP_VMEXIT + exit_code; - env->error_code = exit_info_1; + cs->exception_index = EXCP_VMEXIT; + x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_code), + exit_code); + + x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, + control.exit_info_1), exit_info_1), /* remove any pending exception */ env->old_exception = -1; cpu_loop_exit(cs); } -void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) +void do_vmexit(CPUX86State *env) { CPUState *cs = env_cpu(env); uint32_t int_ctl; @@ -762,11 +766,6 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) env->vm_hsave + offsetof(struct vmcb, save.dr7)); /* other setups */ - x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_code), - exit_code); - x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), - exit_info_1); - x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_int_info), x86_ldl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, |