diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-04 16:08:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-04 16:08:05 -0400 |
| commit | 66cecb67894b35c6af17eb4e6b6aaec6c8957c2e (patch) | |
| tree | c1986d590632735047174c5587d0b22b45b47a1e /arch/mips | |
| parent | 34c510b2eecd2fb8414998f54ce12c94e16d78a0 (diff) | |
| parent | d9092f52d7e61dd1557f2db2400ddb430e85937e (diff) | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM updates from Paolo Bonzini:
"One NULL pointer dereference, and two fixes for regressions introduced
during the merge window.
The rest are fixes for MIPS, s390 and nested VMX"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
kvm: x86: Check memopp before dereference (CVE-2016-8630)
kvm: nVMX: VMCLEAR an active shadow VMCS after last use
KVM: x86: drop TSC offsetting kvm_x86_ops to fix KVM_GET/SET_CLOCK
KVM: x86: fix wbinvd_dirty_mask use-after-free
kvm/x86: Show WRMSR data is in hex
kvm: nVMX: Fix kernel panics induced by illegal INVEPT/INVVPID types
KVM: document lock orders
KVM: fix OOPS on flush_work
KVM: s390: Fix STHYI buffer alignment for diag224
KVM: MIPS: Precalculate MMIO load resume PC
KVM: MIPS: Make ERET handle ERL before EXL
KVM: MIPS: Fix lazy user ASID regenerate for SMP
Diffstat (limited to 'arch/mips')
| -rw-r--r-- | arch/mips/include/asm/kvm_host.h | 7 | ||||
| -rw-r--r-- | arch/mips/kvm/emulate.c | 32 | ||||
| -rw-r--r-- | arch/mips/kvm/mips.c | 5 | ||||
| -rw-r--r-- | arch/mips/kvm/mmu.c | 4 |
4 files changed, 27 insertions, 21 deletions
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 07f58cfc1ab9..bebec370324f 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h | |||
| @@ -293,7 +293,10 @@ struct kvm_vcpu_arch { | |||
| 293 | /* Host KSEG0 address of the EI/DI offset */ | 293 | /* Host KSEG0 address of the EI/DI offset */ |
| 294 | void *kseg0_commpage; | 294 | void *kseg0_commpage; |
| 295 | 295 | ||
| 296 | u32 io_gpr; /* GPR used as IO source/target */ | 296 | /* Resume PC after MMIO completion */ |
| 297 | unsigned long io_pc; | ||
| 298 | /* GPR used as IO source/target */ | ||
| 299 | u32 io_gpr; | ||
| 297 | 300 | ||
| 298 | struct hrtimer comparecount_timer; | 301 | struct hrtimer comparecount_timer; |
| 299 | /* Count timer control KVM register */ | 302 | /* Count timer control KVM register */ |
| @@ -315,8 +318,6 @@ struct kvm_vcpu_arch { | |||
| 315 | /* Bitmask of pending exceptions to be cleared */ | 318 | /* Bitmask of pending exceptions to be cleared */ |
| 316 | unsigned long pending_exceptions_clr; | 319 | unsigned long pending_exceptions_clr; |
| 317 | 320 | ||
| 318 | u32 pending_load_cause; | ||
| 319 | |||
| 320 | /* Save/Restore the entryhi register when are are preempted/scheduled back in */ | 321 | /* Save/Restore the entryhi register when are are preempted/scheduled back in */ |
| 321 | unsigned long preempt_entryhi; | 322 | unsigned long preempt_entryhi; |
| 322 | 323 | ||
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 8770f32c9e0b..aa0937423e28 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c | |||
| @@ -790,15 +790,15 @@ enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu) | |||
| 790 | struct mips_coproc *cop0 = vcpu->arch.cop0; | 790 | struct mips_coproc *cop0 = vcpu->arch.cop0; |
| 791 | enum emulation_result er = EMULATE_DONE; | 791 | enum emulation_result er = EMULATE_DONE; |
| 792 | 792 | ||
| 793 | if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { | 793 | if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { |
| 794 | kvm_clear_c0_guest_status(cop0, ST0_ERL); | ||
| 795 | vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0); | ||
| 796 | } else if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { | ||
| 794 | kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc, | 797 | kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc, |
| 795 | kvm_read_c0_guest_epc(cop0)); | 798 | kvm_read_c0_guest_epc(cop0)); |
| 796 | kvm_clear_c0_guest_status(cop0, ST0_EXL); | 799 | kvm_clear_c0_guest_status(cop0, ST0_EXL); |
| 797 | vcpu->arch.pc = kvm_read_c0_guest_epc(cop0); | 800 | vcpu->arch.pc = kvm_read_c0_guest_epc(cop0); |
| 798 | 801 | ||
| 799 | } else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { | ||
| 800 | kvm_clear_c0_guest_status(cop0, ST0_ERL); | ||
| 801 | vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0); | ||
| 802 | } else { | 802 | } else { |
| 803 | kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n", | 803 | kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n", |
| 804 | vcpu->arch.pc); | 804 | vcpu->arch.pc); |
| @@ -1528,13 +1528,25 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst, | |||
| 1528 | struct kvm_vcpu *vcpu) | 1528 | struct kvm_vcpu *vcpu) |
| 1529 | { | 1529 | { |
| 1530 | enum emulation_result er = EMULATE_DO_MMIO; | 1530 | enum emulation_result er = EMULATE_DO_MMIO; |
| 1531 | unsigned long curr_pc; | ||
| 1531 | u32 op, rt; | 1532 | u32 op, rt; |
| 1532 | u32 bytes; | 1533 | u32 bytes; |
| 1533 | 1534 | ||
| 1534 | rt = inst.i_format.rt; | 1535 | rt = inst.i_format.rt; |
| 1535 | op = inst.i_format.opcode; | 1536 | op = inst.i_format.opcode; |
| 1536 | 1537 | ||
| 1537 | vcpu->arch.pending_load_cause = cause; | 1538 | /* |
| 1539 | * Find the resume PC now while we have safe and easy access to the | ||
| 1540 | * prior branch instruction, and save it for | ||
| 1541 | * kvm_mips_complete_mmio_load() to restore later. | ||
| 1542 | */ | ||
| 1543 | curr_pc = vcpu->arch.pc; | ||
| 1544 | er = update_pc(vcpu, cause); | ||
| 1545 | if (er == EMULATE_FAIL) | ||
| 1546 | return er; | ||
| 1547 | vcpu->arch.io_pc = vcpu->arch.pc; | ||
| 1548 | vcpu->arch.pc = curr_pc; | ||
| 1549 | |||
| 1538 | vcpu->arch.io_gpr = rt; | 1550 | vcpu->arch.io_gpr = rt; |
| 1539 | 1551 | ||
| 1540 | switch (op) { | 1552 | switch (op) { |
| @@ -2494,9 +2506,8 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, | |||
| 2494 | goto done; | 2506 | goto done; |
| 2495 | } | 2507 | } |
| 2496 | 2508 | ||
| 2497 | er = update_pc(vcpu, vcpu->arch.pending_load_cause); | 2509 | /* Restore saved resume PC */ |
| 2498 | if (er == EMULATE_FAIL) | 2510 | vcpu->arch.pc = vcpu->arch.io_pc; |
| 2499 | return er; | ||
| 2500 | 2511 | ||
| 2501 | switch (run->mmio.len) { | 2512 | switch (run->mmio.len) { |
| 2502 | case 4: | 2513 | case 4: |
| @@ -2518,11 +2529,6 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu, | |||
| 2518 | break; | 2529 | break; |
| 2519 | } | 2530 | } |
| 2520 | 2531 | ||
| 2521 | if (vcpu->arch.pending_load_cause & CAUSEF_BD) | ||
| 2522 | kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n", | ||
| 2523 | vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr, | ||
| 2524 | vcpu->mmio_needed); | ||
| 2525 | |||
| 2526 | done: | 2532 | done: |
| 2527 | return er; | 2533 | return er; |
| 2528 | } | 2534 | } |
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 622037d851a3..06a60b19acfb 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c | |||
| @@ -426,7 +426,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | |||
| 426 | static void kvm_mips_check_asids(struct kvm_vcpu *vcpu) | 426 | static void kvm_mips_check_asids(struct kvm_vcpu *vcpu) |
| 427 | { | 427 | { |
| 428 | struct mips_coproc *cop0 = vcpu->arch.cop0; | 428 | struct mips_coproc *cop0 = vcpu->arch.cop0; |
| 429 | int cpu = smp_processor_id(); | 429 | int i, cpu = smp_processor_id(); |
| 430 | unsigned int gasid; | 430 | unsigned int gasid; |
| 431 | 431 | ||
| 432 | /* | 432 | /* |
| @@ -442,6 +442,9 @@ static void kvm_mips_check_asids(struct kvm_vcpu *vcpu) | |||
| 442 | vcpu); | 442 | vcpu); |
| 443 | vcpu->arch.guest_user_asid[cpu] = | 443 | vcpu->arch.guest_user_asid[cpu] = |
| 444 | vcpu->arch.guest_user_mm.context.asid[cpu]; | 444 | vcpu->arch.guest_user_mm.context.asid[cpu]; |
| 445 | for_each_possible_cpu(i) | ||
| 446 | if (i != cpu) | ||
| 447 | vcpu->arch.guest_user_asid[cpu] = 0; | ||
| 445 | vcpu->arch.last_user_gasid = gasid; | 448 | vcpu->arch.last_user_gasid = gasid; |
| 446 | } | 449 | } |
| 447 | } | 450 | } |
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index 03883ba806e2..3b677c851be0 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c | |||
| @@ -260,13 +260,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
| 260 | 260 | ||
| 261 | if ((vcpu->arch.guest_user_asid[cpu] ^ asid_cache(cpu)) & | 261 | if ((vcpu->arch.guest_user_asid[cpu] ^ asid_cache(cpu)) & |
| 262 | asid_version_mask(cpu)) { | 262 | asid_version_mask(cpu)) { |
| 263 | u32 gasid = kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & | ||
| 264 | KVM_ENTRYHI_ASID; | ||
| 265 | |||
| 266 | kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu); | 263 | kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu); |
| 267 | vcpu->arch.guest_user_asid[cpu] = | 264 | vcpu->arch.guest_user_asid[cpu] = |
| 268 | vcpu->arch.guest_user_mm.context.asid[cpu]; | 265 | vcpu->arch.guest_user_mm.context.asid[cpu]; |
| 269 | vcpu->arch.last_user_gasid = gasid; | ||
| 270 | newasid++; | 266 | newasid++; |
| 271 | 267 | ||
| 272 | kvm_debug("[%d]: cpu_context: %#lx\n", cpu, | 268 | kvm_debug("[%d]: cpu_context: %#lx\n", cpu, |
