Loading arch/powerpc/include/asm/kvm_book3s.h +2 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,8 @@ extern long kvmppc_hv_get_dirty_log_hpt(struct kvm *kvm, extern void kvmppc_harvest_vpa_dirty(struct kvmppc_vpa *vpa, struct kvm_memory_slot *memslot, unsigned long *map); extern unsigned long kvmppc_filter_lpcr_hv(struct kvm *kvm, unsigned long lpcr); extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask); extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr); Loading arch/powerpc/include/asm/kvm_ppc.h +1 −2 Original line number Diff line number Diff line Loading @@ -767,8 +767,7 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long pte_index, unsigned long avpn); long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu); long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long pte_index, unsigned long avpn, unsigned long va); unsigned long pte_index, unsigned long avpn); long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long pte_index); long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags, Loading arch/powerpc/kernel/exceptions-64s.S +7 −8 Original line number Diff line number Diff line Loading @@ -2503,8 +2503,6 @@ EXC_VIRT_NONE(0x5100, 0x100) INT_DEFINE_BEGIN(cbe_system_error) IVEC=0x1200 IHSRR=1 IKVM_SKIP=1 IKVM_REAL=1 INT_DEFINE_END(cbe_system_error) EXC_REAL_BEGIN(cbe_system_error, 0x1200, 0x100) Loading @@ -2524,11 +2522,16 @@ EXC_REAL_NONE(0x1200, 0x100) EXC_VIRT_NONE(0x5200, 0x100) #endif /** * Interrupt 0x1300 - Instruction Address Breakpoint Interrupt. * This has been removed from the ISA before 2.01, which is the earliest * 64-bit BookS ISA supported, however the G5 / 970 implements this * interrupt with a non-architected feature available through the support * processor interface. */ INT_DEFINE_BEGIN(instruction_breakpoint) IVEC=0x1300 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_SKIP=1 IKVM_REAL=1 #endif INT_DEFINE_END(instruction_breakpoint) Loading Loading @@ -2674,8 +2677,6 @@ EXC_COMMON_BEGIN(denorm_exception_common) INT_DEFINE_BEGIN(cbe_maintenance) IVEC=0x1600 IHSRR=1 IKVM_SKIP=1 IKVM_REAL=1 INT_DEFINE_END(cbe_maintenance) EXC_REAL_BEGIN(cbe_maintenance, 0x1600, 0x100) Loading Loading @@ -2727,8 +2728,6 @@ EXC_COMMON_BEGIN(altivec_assist_common) INT_DEFINE_BEGIN(cbe_thermal) IVEC=0x1800 IHSRR=1 IKVM_SKIP=1 IKVM_REAL=1 INT_DEFINE_END(cbe_thermal) EXC_REAL_BEGIN(cbe_thermal, 0x1800, 0x100) Loading arch/powerpc/kvm/book3s_hv.c +65 −20 Original line number Diff line number Diff line Loading @@ -803,7 +803,10 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, vcpu->arch.dawrx1 = value2; return H_SUCCESS; case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE: /* KVM does not support mflags=2 (AIL=2) */ /* * KVM does not support mflags=2 (AIL=2) and AIL=1 is reserved. * Keep this in synch with kvmppc_filter_guest_lpcr_hv. */ if (mflags != 0 && mflags != 3) return H_UNSUPPORTED_FLAG_START; return H_TOO_HARD; Loading Loading @@ -1635,6 +1638,41 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu, return 0; } /* * Enforce limits on guest LPCR values based on hardware availability, * guest configuration, and possibly hypervisor support and security * concerns. */ unsigned long kvmppc_filter_lpcr_hv(struct kvm *kvm, unsigned long lpcr) { /* LPCR_TC only applies to HPT guests */ if (kvm_is_radix(kvm)) lpcr &= ~LPCR_TC; /* On POWER8 and above, userspace can modify AIL */ if (!cpu_has_feature(CPU_FTR_ARCH_207S)) lpcr &= ~LPCR_AIL; if ((lpcr & LPCR_AIL) != LPCR_AIL_3) lpcr &= ~LPCR_AIL; /* LPCR[AIL]=1/2 is disallowed */ /* * On POWER9, allow userspace to enable large decrementer for the * guest, whether or not the host has it enabled. */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) lpcr &= ~LPCR_LD; return lpcr; } static void verify_lpcr(struct kvm *kvm, unsigned long lpcr) { if (lpcr != kvmppc_filter_lpcr_hv(kvm, lpcr)) { WARN_ONCE(1, "lpcr 0x%lx differs from filtered 0x%lx\n", lpcr, kvmppc_filter_lpcr_hv(kvm, lpcr)); } } static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, bool preserve_top32) { Loading @@ -1643,6 +1681,23 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, u64 mask; spin_lock(&vc->lock); /* * Userspace can only modify * DPFD (default prefetch depth), ILE (interrupt little-endian), * TC (translation control), AIL (alternate interrupt location), * LD (large decrementer). * These are subject to restrictions from kvmppc_filter_lcpr_hv(). */ mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD; /* Broken 32-bit version of LPCR must not clear top bits */ if (preserve_top32) mask &= 0xFFFFFFFF; new_lpcr = kvmppc_filter_lpcr_hv(kvm, (vc->lpcr & ~mask) | (new_lpcr & mask)); /* * If ILE (interrupt little-endian) has changed, update the * MSR_LE bit in the intr_msr for each vcpu in this vcore. Loading @@ -1661,25 +1716,8 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, } } /* * Userspace can only modify DPFD (default prefetch depth), * ILE (interrupt little-endian) and TC (translation control). * On POWER8 and POWER9 userspace can also modify AIL (alt. interrupt loc.). */ mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; if (cpu_has_feature(CPU_FTR_ARCH_207S)) mask |= LPCR_AIL; /* * On POWER9, allow userspace to enable large decrementer for the * guest, whether or not the host has it enabled. */ if (cpu_has_feature(CPU_FTR_ARCH_300)) mask |= LPCR_LD; vc->lpcr = new_lpcr; /* Broken 32-bit version of LPCR must not clear top bits */ if (preserve_top32) mask &= 0xFFFFFFFF; vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); spin_unlock(&vc->lock); } Loading Loading @@ -3728,7 +3766,10 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, vcpu->arch.dec_expires = dec + tb; vcpu->cpu = -1; vcpu->arch.thread_cpu = -1; /* Save guest CTRL register, set runlatch to 1 */ vcpu->arch.ctrl = mfspr(SPRN_CTRLF); if (!(vcpu->arch.ctrl & 1)) mtspr(SPRN_CTRLT, vcpu->arch.ctrl | 1); vcpu->arch.iamr = mfspr(SPRN_IAMR); vcpu->arch.pspb = mfspr(SPRN_PSPB); Loading @@ -3749,7 +3790,6 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, mtspr(SPRN_DSCR, host_dscr); mtspr(SPRN_TIDR, host_tidr); mtspr(SPRN_IAMR, host_iamr); mtspr(SPRN_PSPB, 0); if (host_amr != vcpu->arch.amr) mtspr(SPRN_AMR, host_amr); Loading Loading @@ -4641,8 +4681,10 @@ void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask) struct kvmppc_vcore *vc = kvm->arch.vcores[i]; if (!vc) continue; spin_lock(&vc->lock); vc->lpcr = (vc->lpcr & ~mask) | lpcr; verify_lpcr(kvm, vc->lpcr); spin_unlock(&vc->lock); if (++cores_done >= kvm->arch.online_vcores) break; Loading Loading @@ -4970,6 +5012,7 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) kvmppc_setup_partition_table(kvm); } verify_lpcr(kvm, lpcr); kvm->arch.lpcr = lpcr; /* Initialization for future HPT resizes */ Loading Loading @@ -5369,8 +5412,10 @@ static unsigned int default_hcall_list[] = { H_READ, H_PROTECT, H_BULK_REMOVE, #ifdef CONFIG_SPAPR_TCE_IOMMU H_GET_TCE, H_PUT_TCE, #endif H_SET_DABR, H_SET_XDABR, H_CEDE, Loading arch/powerpc/kvm/book3s_hv_builtin.c +3 −0 Original line number Diff line number Diff line Loading @@ -662,6 +662,9 @@ static void kvmppc_end_cede(struct kvm_vcpu *vcpu) void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr) { /* Guest must always run with ME enabled, HV disabled. */ msr = (msr | MSR_ME) & ~MSR_HV; /* * Check for illegal transactional state bit combination * and if we find it, force the TS field to a safe state. Loading Loading
arch/powerpc/include/asm/kvm_book3s.h +2 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,8 @@ extern long kvmppc_hv_get_dirty_log_hpt(struct kvm *kvm, extern void kvmppc_harvest_vpa_dirty(struct kvmppc_vpa *vpa, struct kvm_memory_slot *memslot, unsigned long *map); extern unsigned long kvmppc_filter_lpcr_hv(struct kvm *kvm, unsigned long lpcr); extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask); extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr); Loading
arch/powerpc/include/asm/kvm_ppc.h +1 −2 Original line number Diff line number Diff line Loading @@ -767,8 +767,7 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long pte_index, unsigned long avpn); long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu); long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long pte_index, unsigned long avpn, unsigned long va); unsigned long pte_index, unsigned long avpn); long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, unsigned long pte_index); long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags, Loading
arch/powerpc/kernel/exceptions-64s.S +7 −8 Original line number Diff line number Diff line Loading @@ -2503,8 +2503,6 @@ EXC_VIRT_NONE(0x5100, 0x100) INT_DEFINE_BEGIN(cbe_system_error) IVEC=0x1200 IHSRR=1 IKVM_SKIP=1 IKVM_REAL=1 INT_DEFINE_END(cbe_system_error) EXC_REAL_BEGIN(cbe_system_error, 0x1200, 0x100) Loading @@ -2524,11 +2522,16 @@ EXC_REAL_NONE(0x1200, 0x100) EXC_VIRT_NONE(0x5200, 0x100) #endif /** * Interrupt 0x1300 - Instruction Address Breakpoint Interrupt. * This has been removed from the ISA before 2.01, which is the earliest * 64-bit BookS ISA supported, however the G5 / 970 implements this * interrupt with a non-architected feature available through the support * processor interface. */ INT_DEFINE_BEGIN(instruction_breakpoint) IVEC=0x1300 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE IKVM_SKIP=1 IKVM_REAL=1 #endif INT_DEFINE_END(instruction_breakpoint) Loading Loading @@ -2674,8 +2677,6 @@ EXC_COMMON_BEGIN(denorm_exception_common) INT_DEFINE_BEGIN(cbe_maintenance) IVEC=0x1600 IHSRR=1 IKVM_SKIP=1 IKVM_REAL=1 INT_DEFINE_END(cbe_maintenance) EXC_REAL_BEGIN(cbe_maintenance, 0x1600, 0x100) Loading Loading @@ -2727,8 +2728,6 @@ EXC_COMMON_BEGIN(altivec_assist_common) INT_DEFINE_BEGIN(cbe_thermal) IVEC=0x1800 IHSRR=1 IKVM_SKIP=1 IKVM_REAL=1 INT_DEFINE_END(cbe_thermal) EXC_REAL_BEGIN(cbe_thermal, 0x1800, 0x100) Loading
arch/powerpc/kvm/book3s_hv.c +65 −20 Original line number Diff line number Diff line Loading @@ -803,7 +803,10 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, vcpu->arch.dawrx1 = value2; return H_SUCCESS; case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE: /* KVM does not support mflags=2 (AIL=2) */ /* * KVM does not support mflags=2 (AIL=2) and AIL=1 is reserved. * Keep this in synch with kvmppc_filter_guest_lpcr_hv. */ if (mflags != 0 && mflags != 3) return H_UNSUPPORTED_FLAG_START; return H_TOO_HARD; Loading Loading @@ -1635,6 +1638,41 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu, return 0; } /* * Enforce limits on guest LPCR values based on hardware availability, * guest configuration, and possibly hypervisor support and security * concerns. */ unsigned long kvmppc_filter_lpcr_hv(struct kvm *kvm, unsigned long lpcr) { /* LPCR_TC only applies to HPT guests */ if (kvm_is_radix(kvm)) lpcr &= ~LPCR_TC; /* On POWER8 and above, userspace can modify AIL */ if (!cpu_has_feature(CPU_FTR_ARCH_207S)) lpcr &= ~LPCR_AIL; if ((lpcr & LPCR_AIL) != LPCR_AIL_3) lpcr &= ~LPCR_AIL; /* LPCR[AIL]=1/2 is disallowed */ /* * On POWER9, allow userspace to enable large decrementer for the * guest, whether or not the host has it enabled. */ if (!cpu_has_feature(CPU_FTR_ARCH_300)) lpcr &= ~LPCR_LD; return lpcr; } static void verify_lpcr(struct kvm *kvm, unsigned long lpcr) { if (lpcr != kvmppc_filter_lpcr_hv(kvm, lpcr)) { WARN_ONCE(1, "lpcr 0x%lx differs from filtered 0x%lx\n", lpcr, kvmppc_filter_lpcr_hv(kvm, lpcr)); } } static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, bool preserve_top32) { Loading @@ -1643,6 +1681,23 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, u64 mask; spin_lock(&vc->lock); /* * Userspace can only modify * DPFD (default prefetch depth), ILE (interrupt little-endian), * TC (translation control), AIL (alternate interrupt location), * LD (large decrementer). * These are subject to restrictions from kvmppc_filter_lcpr_hv(). */ mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD; /* Broken 32-bit version of LPCR must not clear top bits */ if (preserve_top32) mask &= 0xFFFFFFFF; new_lpcr = kvmppc_filter_lpcr_hv(kvm, (vc->lpcr & ~mask) | (new_lpcr & mask)); /* * If ILE (interrupt little-endian) has changed, update the * MSR_LE bit in the intr_msr for each vcpu in this vcore. Loading @@ -1661,25 +1716,8 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, } } /* * Userspace can only modify DPFD (default prefetch depth), * ILE (interrupt little-endian) and TC (translation control). * On POWER8 and POWER9 userspace can also modify AIL (alt. interrupt loc.). */ mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; if (cpu_has_feature(CPU_FTR_ARCH_207S)) mask |= LPCR_AIL; /* * On POWER9, allow userspace to enable large decrementer for the * guest, whether or not the host has it enabled. */ if (cpu_has_feature(CPU_FTR_ARCH_300)) mask |= LPCR_LD; vc->lpcr = new_lpcr; /* Broken 32-bit version of LPCR must not clear top bits */ if (preserve_top32) mask &= 0xFFFFFFFF; vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); spin_unlock(&vc->lock); } Loading Loading @@ -3728,7 +3766,10 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, vcpu->arch.dec_expires = dec + tb; vcpu->cpu = -1; vcpu->arch.thread_cpu = -1; /* Save guest CTRL register, set runlatch to 1 */ vcpu->arch.ctrl = mfspr(SPRN_CTRLF); if (!(vcpu->arch.ctrl & 1)) mtspr(SPRN_CTRLT, vcpu->arch.ctrl | 1); vcpu->arch.iamr = mfspr(SPRN_IAMR); vcpu->arch.pspb = mfspr(SPRN_PSPB); Loading @@ -3749,7 +3790,6 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, mtspr(SPRN_DSCR, host_dscr); mtspr(SPRN_TIDR, host_tidr); mtspr(SPRN_IAMR, host_iamr); mtspr(SPRN_PSPB, 0); if (host_amr != vcpu->arch.amr) mtspr(SPRN_AMR, host_amr); Loading Loading @@ -4641,8 +4681,10 @@ void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask) struct kvmppc_vcore *vc = kvm->arch.vcores[i]; if (!vc) continue; spin_lock(&vc->lock); vc->lpcr = (vc->lpcr & ~mask) | lpcr; verify_lpcr(kvm, vc->lpcr); spin_unlock(&vc->lock); if (++cores_done >= kvm->arch.online_vcores) break; Loading Loading @@ -4970,6 +5012,7 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) kvmppc_setup_partition_table(kvm); } verify_lpcr(kvm, lpcr); kvm->arch.lpcr = lpcr; /* Initialization for future HPT resizes */ Loading Loading @@ -5369,8 +5412,10 @@ static unsigned int default_hcall_list[] = { H_READ, H_PROTECT, H_BULK_REMOVE, #ifdef CONFIG_SPAPR_TCE_IOMMU H_GET_TCE, H_PUT_TCE, #endif H_SET_DABR, H_SET_XDABR, H_CEDE, Loading
arch/powerpc/kvm/book3s_hv_builtin.c +3 −0 Original line number Diff line number Diff line Loading @@ -662,6 +662,9 @@ static void kvmppc_end_cede(struct kvm_vcpu *vcpu) void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr) { /* Guest must always run with ME enabled, HV disabled. */ msr = (msr | MSR_ME) & ~MSR_HV; /* * Check for illegal transactional state bit combination * and if we find it, force the TS field to a safe state. Loading