This series contains fixes for some issues observed since the KVM arm64
pull request for 4.17.
It supersedes the previous v1 [1].
The first patch (from Mark Rutland) adds a straightforward helper to
modify particular bits in a system register conditionally. This is used
by patch 3 (though obviously it could be coded round and patch 1
dropped, if preferred).
See other patches for details of the individual fixes and changes from
the previous posting.
[1] [PATCH 0/4] KVM: arm64: FPSIMD/SVE fixes for 4.17
http://lists.infradead.org/pipermail/linux-arm-kernel/2018-June/584107.html
Dave Martin (3):
KVM: arm64: Don't mask softirq with IRQs disabled in vcpu_put()
KVM: arm64/sve: Fix SVE trap restoration for non-current tasks
KVM: arm64: Avoid mistaken attempts to save SVE state for vcpus
Mark Rutland (1):
arm64: introduce sysreg_clear_set()
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/include/asm/sysreg.h | 11 +++++++++++
arch/arm64/kvm/fpsimd.c | 36 +++++++++++++++++++++++++++---------
3 files changed, 39 insertions(+), 9 deletions(-)
--
2.1.4
From: Mark Rutland <mark.rutland@arm.com>
Currently we have a couple of helpers to manipulate bits in particular
sysregs:
* config_sctlr_el1(u32 clear, u32 set)
* change_cpacr(u64 val, u64 mask)
The parameters of these differ in naming convention, order, and size,
which is unfortunate. They also differ slightly in behaviour, as
change_cpacr() skips the sysreg write if the bits are unchanged, which
is a useful optimization when sysreg writes are expensive.
Before we gain more yet another sysreg manipulation function, let's
unify these with a common helper, providing a consistent order for
clear/set operands, and the write skipping behaviour from
change_cpacr(). Code will be migrated to the new helper in subsequent
patches.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
---
arch/arm64/include/asm/sysreg.h | 11 +++++++++++
1 file changed, 11 insertions(+)
On Fri, Jun 15, 2018 at 04:47:23PM +0100, Dave P Martin wrote:
From: Mark Rutland <mark.rutland@arm.com>
Currently we have a couple of helpers to manipulate bits in particular
sysregs:
* config_sctlr_el1(u32 clear, u32 set)
* change_cpacr(u64 val, u64 mask)
The parameters of these differ in naming convention, order, and size,
which is unfortunate. They also differ slightly in behaviour, as
change_cpacr() skips the sysreg write if the bits are unchanged, which
is a useful optimization when sysreg writes are expensive.
Before we gain more yet another sysreg manipulation function, let's
unify these with a common helper, providing a consistent order for
clear/set operands, and the write skipping behaviour from
change_cpacr(). Code will be migrated to the new helper in subsequent
patches.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Since you are submitting this patch, it should have your signed-off-by
as well. Other than that:
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
On Fri, Jun 15, 2018 at 05:21:25PM +0100, Catalin Marinas wrote:
On Fri, Jun 15, 2018 at 04:47:23PM +0100, Dave P Martin wrote:
quoted
From: Mark Rutland <mark.rutland@arm.com>
Currently we have a couple of helpers to manipulate bits in particular
sysregs:
* config_sctlr_el1(u32 clear, u32 set)
* change_cpacr(u64 val, u64 mask)
The parameters of these differ in naming convention, order, and size,
which is unfortunate. They also differ slightly in behaviour, as
change_cpacr() skips the sysreg write if the bits are unchanged, which
is a useful optimization when sysreg writes are expensive.
Before we gain more yet another sysreg manipulation function, let's
unify these with a common helper, providing a consistent order for
clear/set operands, and the write skipping behaviour from
change_cpacr(). Code will be migrated to the new helper in subsequent
patches.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dave Martin <dave.martin@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <redacted>
Since you are submitting this patch, it should have your signed-off-by
as well. Other than that:
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Oops, added locally.
I had considered this optional if the patch was unmodified from the
original author, but I guess I at least applied it on a different base.
In any case, I can see why it would be considered mandatory.
Cheers
---Dave
Commit e6b673b ("KVM: arm64: Optimise FPSIMD handling to reduce
guest/host thrashing") introduces a specific helper
kvm_arch_vcpu_put_fp() for saving the vcpu FPSIMD state during
vcpu_put().
This function uses local_bh_disable()/_enable() to protect the
FPSIMD context manipulation from interruption by softirqs.
This approach is not correct, because vcpu_put() can be invoked
either from the KVM host vcpu thread (when exiting the vcpu run
loop), or via a preempt notifier. In the former case, only
preemption is disabled. In the latter case, the function is called
from inside __schedule(), which means that IRQs are disabled.
Use of local_bh_disable()/_enable() with IRQs disabled is considerd
an error, resulting in lockdep splats while running VMs if lockdep
is enabled.
This patch disables IRQs instead of attempting to disable softirqs,
avoiding the problem of calling local_bh_enable() with IRQs
disabled in the __schedule() path. This creates an additional
interrupt blackout during vcpu run loop exit, but this is the rare
case and the blackout latency is still less than that of
__schedule().
Fixes: e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to reduce guest/host thrashing")
Reported-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
Changes since v1:
Requested by Marc Zyngier:
* Disable IRQs unconditionally instead of attempting to conditionally
disable softirqs. This creates an additional interrupt blackout
during vcpu run loop exit. This is the rare case, and the blackout
latency is still less than that of __schedule().
---
arch/arm64/kvm/fpsimd.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
Commit e6b673b ("KVM: arm64: Optimise FPSIMD handling to reduce
guest/host thrashing") attempts to restore the configuration of
userspace SVE trapping via a call to fpsimd_bind_task_to_cpu(), but
the logic for determining when to do this is not correct.
The patch makes the errnoenous assumption that the only task that
may try to enter userspace with the currently loaded FPSIMD/SVE
register content is current. This may not be the case however: if
some other user task T is scheduled on the CPU during the execution
of the KVM run loop, and the vcpu does not try to use the registers
in the meantime, then T's state may be left there intact. If T
happens to be the next task to enter userspace on this CPU then the
hooks for reloading the register state and configuring traps will
be skipped.
(Also, current never has SVE state at this point anyway and should
always have the trap enabled, as a side-effect of the ioctl()
syscall needed to reach the KVM run loop in the first place.)
This patch instead restores the state of the EL0 trap from the
state observed at the most recent vcpu_load(), ensuring that the
trap is set correctly for the loaded context (if any).
Fixes: e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to reduce guest/host thrashing")
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/kvm/fpsimd.c | 24 ++++++++++++++++++++----
2 files changed, 21 insertions(+), 4 deletions(-)
@@ -103,9 +110,18 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)/* Clean guest FP state to memory and invalidate cpu view */fpsimd_save();fpsimd_flush_cpu_state();-}elseif(!test_thread_flag(TIF_FOREIGN_FPSTATE)){-/* Ensure user trap controls are correctly restored */-fpsimd_bind_task_to_cpu();+}elseif(system_supports_sve()){+/*+*TheFPSIMD/SVEstateintheCPUhasnotbeentouched,andwe+*haveSVE(andVHE):CPACR_EL1(aliasCPTR_EL2)hasbeen+*resettoCPACR_EL1_DEFAULTbytheHypcode,disablingSVE+*forEL0.Toavoidspurioustraps,restorethetrapstate+*seenbykvm_arch_vcpu_load_fp():+*/+if(vcpu->arch.flags&KVM_ARM64_HOST_SVE_ENABLED)+sysreg_clear_set(CPACR_EL1,0,CPACR_EL1_ZEN_EL0EN);+else+sysreg_clear_set(CPACR_EL1,CPACR_EL1_ZEN_EL0EN,0);}local_irq_restore(flags);
Commit e6b673b ("KVM: arm64: Optimise FPSIMD handling to reduce
guest/host thrashing") uses fpsimd_save() to save the FPSIMD state
for a vcpu when scheduling the vcpu out. However, currently
current's value of TIF_SVE is restored before calling fpsimd_save()
which means that fpsimd_save() may erroneously attempt to save SVE
state from the vcpu. This enables current's vector state to be
polluted with guest data. current->thread.sve_state may be
unallocated or not large enough, so this can also trigger a NULL
dereference or buffer overrun.
Instead of this, TIF_SVE should be configured properly for the
guest when calling fpsimd_save() with the vcpu context loaded.
This patch ensures this by delaying restoration of current's
TIF_SVE until after the call to fpsimd_save().
Fixes: e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to reduce guest/host thrashing")
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/kvm/fpsimd.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -103,9 +103,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)local_irq_save(flags);-update_thread_flag(TIF_SVE,-vcpu->arch.flags&KVM_ARM64_HOST_SVE_IN_USE);-if(vcpu->arch.flags&KVM_ARM64_FP_ENABLED){/* Clean guest FP state to memory and invalidate cpu view */fpsimd_save();
On Fri, Jun 15, 2018 at 04:47:22PM +0100, Dave Martin wrote:
This series contains fixes for some issues observed since the KVM arm64
pull request for 4.17.
Groan. Again, this should read "4.18". Apologies for the confusion!
Fixed locally in case I respin.
Cheers
---Dave
It supersedes the previous v1 [1].
The first patch (from Mark Rutland) adds a straightforward helper to
modify particular bits in a system register conditionally. This is used
by patch 3 (though obviously it could be coded round and patch 1
dropped, if preferred).
See other patches for details of the individual fixes and changes from
the previous posting.
[1] [PATCH 0/4] KVM: arm64: FPSIMD/SVE fixes for 4.17
http://lists.infradead.org/pipermail/linux-arm-kernel/2018-June/584107.html
Dave Martin (3):
KVM: arm64: Don't mask softirq with IRQs disabled in vcpu_put()
KVM: arm64/sve: Fix SVE trap restoration for non-current tasks
KVM: arm64: Avoid mistaken attempts to save SVE state for vcpus
Mark Rutland (1):
arm64: introduce sysreg_clear_set()
arch/arm64/include/asm/kvm_host.h | 1 +
arch/arm64/include/asm/sysreg.h | 11 +++++++++++
arch/arm64/kvm/fpsimd.c | 36 +++++++++++++++++++++++++++---------
3 files changed, 39 insertions(+), 9 deletions(-)
--
2.1.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel