* [PATCH v10 10/18] KVM: arm64: Optimise FPSIMD handling to reduce guest/host thrashing
From: Alex Bennée @ 2018-05-24 10:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527005119-6842-11-git-send-email-Dave.Martin@arm.com>
Dave Martin <Dave.Martin@arm.com> writes:
> This patch refactors KVM to align the host and guest FPSIMD
> save/restore logic with each other for arm64. This reduces the
> number of redundant save/restore operations that must occur, and
> reduces the common-case IRQ blackout time during guest exit storms
> by saving the host state lazily and optimising away the need to
> restore the host state before returning to the run loop.
>
> Four hooks are defined in order to enable this:
>
> * kvm_arch_vcpu_run_map_fp():
> Called on PID change to map necessary bits of current to Hyp.
>
> * kvm_arch_vcpu_load_fp():
> Set up FP/SIMD for entering the KVM run loop (parse as
> "vcpu_load fp").
>
> * kvm_arch_vcpu_ctxsync_fp():
> Get FP/SIMD into a safe state for re-enabling interrupts after a
> guest exit back to the run loop.
>
> For arm64 specifically, this involves updating the host kernel's
> FPSIMD context tracking metadata so that kernel-mode NEON use
> will cause the vcpu's FPSIMD state to be saved back correctly
> into the vcpu struct. This must be done before re-enabling
> interrupts because kernel-mode NEON may be used by softirqs.
>
> * kvm_arch_vcpu_put_fp():
> Save guest FP/SIMD state back to memory and dissociate from the
> CPU ("vcpu_put fp").
>
> Also, the arm64 FPSIMD context switch code is updated to enable it
> to save back FPSIMD state for a vcpu, not just current. A few
> helpers drive this:
>
> * fpsimd_bind_state_to_cpu(struct user_fpsimd_state *fp):
> mark this CPU as having context fp (which may belong to a vcpu)
> currently loaded in its registers. This is the non-task
> equivalent of the static function fpsimd_bind_to_cpu() in
> fpsimd.c.
>
> * task_fpsimd_save():
> exported to allow KVM to save the guest's FPSIMD state back to
> memory on exit from the run loop.
>
> * fpsimd_flush_state():
> invalidate any context's FPSIMD state that is currently loaded.
> Used to disassociate the vcpu from the CPU regs on run loop exit.
>
> These changes allow the run loop to enable interrupts (and thus
> softirqs that may use kernel-mode NEON) without having to save the
> guest's FPSIMD state eagerly.
>
> Some new vcpu_arch fields are added to make all this work. Because
> host FPSIMD state can now be saved back directly into current's
> thread_struct as appropriate, host_cpu_context is no longer used
> for preserving the FPSIMD state. However, it is still needed for
> preserving other things such as the host's system registers. To
> avoid ABI churn, the redundant storage space in host_cpu_context is
> not removed for now.
>
> arch/arm is not addressed by this patch and continues to use its
> current save/restore logic. It could provide implementations of
> the helpers later if desired.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
> Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
>
> ---
>
> Reviewers note: tags retained because this delta is straightforward by
> itself. Please shout if you're not happy!
>
> Changes since v9:
>
> * Remove redundant set_thread_flag(TIF_FOREIGN_FPSTATE) that is now
> implicit in fpsimd_flush_cpu_state().
> ---
> arch/arm/include/asm/kvm_host.h | 8 +++
> arch/arm64/include/asm/fpsimd.h | 6 +++
> arch/arm64/include/asm/kvm_host.h | 21 ++++++++
> arch/arm64/kernel/fpsimd.c | 17 ++++--
> arch/arm64/kvm/Kconfig | 1 +
> arch/arm64/kvm/Makefile | 2 +-
> arch/arm64/kvm/fpsimd.c | 111 ++++++++++++++++++++++++++++++++++++++
> arch/arm64/kvm/hyp/switch.c | 51 +++++++++---------
> virt/kvm/arm/arm.c | 4 ++
> 9 files changed, 191 insertions(+), 30 deletions(-)
> create mode 100644 arch/arm64/kvm/fpsimd.c
>
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index c7c28c8..ac870b2 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -303,6 +303,14 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
> int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
> struct kvm_device_attr *attr);
>
> +/*
> + * VFP/NEON switching is all done by the hyp switch code, so no need to
> + * coordinate with host context handling for this state:
> + */
> +static inline void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) {}
> +static inline void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) {}
> +static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {}
> +
> /* All host FP/SIMD state is restored on guest exit, so nothing to save: */
> static inline void kvm_fpsimd_flush_cpu_state(void) {}
>
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index aa7162a..3e00f70 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -41,6 +41,8 @@ struct task_struct;
> extern void fpsimd_save_state(struct user_fpsimd_state *state);
> extern void fpsimd_load_state(struct user_fpsimd_state *state);
>
> +extern void fpsimd_save(void);
> +
> extern void fpsimd_thread_switch(struct task_struct *next);
> extern void fpsimd_flush_thread(void);
>
> @@ -49,7 +51,11 @@ extern void fpsimd_preserve_current_state(void);
> extern void fpsimd_restore_current_state(void);
> extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
>
> +extern void fpsimd_bind_task_to_cpu(void);
> +extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state);
> +
> extern void fpsimd_flush_task_state(struct task_struct *target);
> +extern void fpsimd_flush_cpu_state(void);
> extern void sve_flush_cpu_state(void);
>
> /* Maximum VL that SVE VL-agnostic software can transparently support */
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 146c167..b3fe730 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -30,6 +30,7 @@
> #include <asm/kvm.h>
> #include <asm/kvm_asm.h>
> #include <asm/kvm_mmio.h>
> +#include <asm/thread_info.h>
>
> #define __KVM_HAVE_ARCH_INTC_INITIALIZED
>
> @@ -238,6 +239,10 @@ struct kvm_vcpu_arch {
>
> /* Pointer to host CPU context */
> kvm_cpu_context_t *host_cpu_context;
> +
> + struct thread_info *host_thread_info; /* hyp VA */
> + struct user_fpsimd_state *host_fpsimd_state; /* hyp VA */
> +
> struct {
> /* {Break,watch}point registers */
> struct kvm_guest_debug_arch regs;
> @@ -295,6 +300,9 @@ struct kvm_vcpu_arch {
>
> /* vcpu_arch flags field values: */
> #define KVM_ARM64_DEBUG_DIRTY (1 << 0)
> +#define KVM_ARM64_FP_ENABLED (1 << 1) /* guest FP regs loaded */
> +#define KVM_ARM64_FP_HOST (1 << 2) /* host FP regs loaded
> */
I may be descending into bike-shedding territory here but it seems a
little incongruous to have _ENABLED = guest FP state when we have _HOST
for host FP state. Why not KVM_ARM64_FP_GUEST?
> +#define KVM_ARM64_HOST_SVE_IN_USE (1 << 3) /* backup for host TIF_SVE */
>
> #define vcpu_gp_regs(v) (&(v)->arch.ctxt.gp_regs)
>
> @@ -423,6 +431,19 @@ static inline void __cpu_init_stage2(void)
> "PARange is %d bits, unsupported configuration!", parange);
> }
>
> +/* Guest/host FPSIMD coordination helpers */
> +int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
> +void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
> +void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu);
> +void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu);
> +
> +#ifdef CONFIG_KVM /* Avoid conflicts with core headers if CONFIG_KVM=n */
> +static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
> +{
> + return kvm_arch_vcpu_run_map_fp(vcpu);
> +}
> +#endif
> +
> /*
> * All host FP/SIMD state is restored on guest exit, so nothing needs
> * doing here except in the SVE case:
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index ba9e7df..ded7ffd 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -265,7 +265,7 @@ static void task_fpsimd_load(void)
> *
> * Softirqs (and preemption) must be disabled.
> */
> -static void fpsimd_save(void)
> +void fpsimd_save(void)
> {
> struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st);
>
> @@ -981,7 +981,7 @@ void fpsimd_signal_preserve_current_state(void)
> * Associate current's FPSIMD context with this cpu
> * Preemption must be disabled when calling this function.
> */
> -static void fpsimd_bind_task_to_cpu(void)
> +void fpsimd_bind_task_to_cpu(void)
> {
> struct fpsimd_last_state_struct *last =
> this_cpu_ptr(&fpsimd_last_state);
> @@ -1001,6 +1001,17 @@ static void fpsimd_bind_task_to_cpu(void)
> }
> }
>
> +void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st)
> +{
> + struct fpsimd_last_state_struct *last =
> + this_cpu_ptr(&fpsimd_last_state);
> +
> + WARN_ON(!in_softirq() && !irqs_disabled());
> +
> + last->st = st;
> + last->sve_in_use = false;
> +}
> +
> /*
> * Load the userland FPSIMD state of 'current' from memory, but only if the
> * FPSIMD state already held in the registers is /not/ the most recent FPSIMD
> @@ -1053,7 +1064,7 @@ void fpsimd_flush_task_state(struct task_struct *t)
> t->thread.fpsimd_cpu = NR_CPUS;
> }
>
> -static inline void fpsimd_flush_cpu_state(void)
> +void fpsimd_flush_cpu_state(void)
> {
> __this_cpu_write(fpsimd_last_state.st, NULL);
> set_thread_flag(TIF_FOREIGN_FPSTATE);
> diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
> index a2e3a5a..47b23bf 100644
> --- a/arch/arm64/kvm/Kconfig
> +++ b/arch/arm64/kvm/Kconfig
> @@ -39,6 +39,7 @@ config KVM
> select HAVE_KVM_IRQ_ROUTING
> select IRQ_BYPASS_MANAGER
> select HAVE_KVM_IRQ_BYPASS
> + select HAVE_KVM_VCPU_RUN_PID_CHANGE
> ---help---
> Support hosting virtualized guest machines.
> We don't support KVM with 16K page tables yet, due to the multiple
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index 93afff9..0f2a135 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -19,7 +19,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
> kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
> kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
> kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
> -kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o
> +kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o
>
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> new file mode 100644
> index 0000000..365933a
> --- /dev/null
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -0,0 +1,111 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * arch/arm64/kvm/fpsimd.c: Guest/host FPSIMD context coordination helpers
> + *
> + * Copyright 2018 Arm Limited
> + * Author: Dave Martin <Dave.Martin@arm.com>
> + */
> +#include <linux/bottom_half.h>
> +#include <linux/sched.h>
> +#include <linux/thread_info.h>
> +#include <linux/kvm_host.h>
> +#include <asm/kvm_asm.h>
> +#include <asm/kvm_host.h>
> +#include <asm/kvm_mmu.h>
> +
> +/*
> + * Called on entry to KVM_RUN unless this vcpu previously ran at least
> + * once and the most recent prior KVM_RUN for this vcpu was called from
> + * the same task as current (highly likely).
> + *
> + * This is guaranteed to execute before kvm_arch_vcpu_load_fp(vcpu),
> + * such that on entering hyp the relevant parts of current are already
> + * mapped.
> + */
> +int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
> +{
> + int ret;
> +
> + struct thread_info *ti = ¤t->thread_info;
> + struct user_fpsimd_state *fpsimd = ¤t->thread.uw.fpsimd_state;
> +
> + /*
> + * Make sure the host task thread flags and fpsimd state are
> + * visible to hyp:
> + */
> + ret = create_hyp_mappings(ti, ti + 1, PAGE_HYP);
> + if (ret)
> + goto error;
> +
> + ret = create_hyp_mappings(fpsimd, fpsimd + 1, PAGE_HYP);
> + if (ret)
> + goto error;
> +
> + vcpu->arch.host_thread_info = kern_hyp_va(ti);
> + vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
> +error:
> + return ret;
> +}
> +
> +/*
> + * Prepare vcpu for saving the host's FPSIMD state and loading the guest's.
> + * The actual loading is done by the FPSIMD access trap taken to hyp.
> + *
> + * Here, we just set the correct metadata to indicate that the FPSIMD
> + * state in the cpu regs (if any) belongs to current on the host.
> + *
> + * TIF_SVE is backed up here, since it may get clobbered with guest state.
> + * This flag is restored by kvm_arch_vcpu_put_fp(vcpu).
> + */
> +void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
> +{
> + BUG_ON(system_supports_sve());
> + BUG_ON(!current->mm);
> +
> + vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | KVM_ARM64_HOST_SVE_IN_USE);
> + vcpu->arch.flags |= KVM_ARM64_FP_HOST;
> + if (test_thread_flag(TIF_SVE))
> + vcpu->arch.flags |= KVM_ARM64_HOST_SVE_IN_USE;
> +}
> +
> +/*
> + * If the guest FPSIMD state was loaded, update the host's context
> + * tracking data mark the CPU FPSIMD regs as dirty and belonging to vcpu
> + * so that they will be written back if the kernel clobbers them due to
> + * kernel-mode NEON before re-entry into the guest.
> + */
> +void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
> +{
> + WARN_ON_ONCE(!irqs_disabled());
> +
> + if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
> + fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs);
> + clear_thread_flag(TIF_FOREIGN_FPSTATE);
> + clear_thread_flag(TIF_SVE);
> + }
> +}
> +
> +/*
> + * Write back the vcpu FPSIMD regs if they are dirty, and invalidate the
> + * cpu FPSIMD regs so that they can't be spuriously reused if this vcpu
> + * disappears and another task or vcpu appears that recycles the same
> + * struct fpsimd_state.
> + */
> +void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
> +{
> + local_bh_disable();
> +
> + 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();
> + fpsimd_flush_cpu_state();
> + } else if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
> + /* Ensure user trap controls are correctly restored */
> + fpsimd_bind_task_to_cpu();
> + }
> +
> + local_bh_enable();
> +}
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index c0796c4..118f300 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -23,19 +23,21 @@
>
> #include <asm/kvm_asm.h>
> #include <asm/kvm_emulate.h>
> +#include <asm/kvm_host.h>
> #include <asm/kvm_hyp.h>
> #include <asm/kvm_mmu.h>
> #include <asm/fpsimd.h>
> #include <asm/debug-monitors.h>
> +#include <asm/thread_info.h>
>
> -static bool __hyp_text __fpsimd_enabled_nvhe(void)
> +/* Check whether the FP regs were dirtied while in the host-side run loop: */
> +static bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu)
> {
> - return !(read_sysreg(cptr_el2) & CPTR_EL2_TFP);
> -}
> + if (vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE)
> + vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
> + KVM_ARM64_FP_HOST);
>
> -static bool fpsimd_enabled_vhe(void)
> -{
> - return !!(read_sysreg(cpacr_el1) & CPACR_EL1_FPEN);
> + return !!(vcpu->arch.flags & KVM_ARM64_FP_ENABLED);
> }
>
> /* Save the 32-bit only FPSIMD system register state */
> @@ -92,7 +94,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
>
> val = read_sysreg(cpacr_el1);
> val |= CPACR_EL1_TTA;
> - val &= ~(CPACR_EL1_FPEN | CPACR_EL1_ZEN);
> + val &= ~CPACR_EL1_ZEN;
> + if (!update_fp_enabled(vcpu))
> + val &= ~CPACR_EL1_FPEN;
> +
> write_sysreg(val, cpacr_el1);
>
> write_sysreg(kvm_get_hyp_vector(), vbar_el1);
> @@ -105,7 +110,10 @@ static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
> __activate_traps_common(vcpu);
>
> val = CPTR_EL2_DEFAULT;
> - val |= CPTR_EL2_TTA | CPTR_EL2_TFP | CPTR_EL2_TZ;
> + val |= CPTR_EL2_TTA | CPTR_EL2_TZ;
> + if (!update_fp_enabled(vcpu))
> + val |= CPTR_EL2_TFP;
> +
> write_sysreg(val, cptr_el2);
> }
>
> @@ -321,8 +329,6 @@ static bool __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
> void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused,
> struct kvm_vcpu *vcpu)
> {
> - kvm_cpu_context_t *host_ctxt;
> -
> if (has_vhe())
> write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> cpacr_el1);
> @@ -332,14 +338,19 @@ void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused,
>
> isb();
>
> - host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
> - __fpsimd_save_state(&host_ctxt->gp_regs.fp_regs);
> + if (vcpu->arch.flags & KVM_ARM64_FP_HOST) {
> + __fpsimd_save_state(vcpu->arch.host_fpsimd_state);
> + vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
> + }
> +
> __fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
>
> /* Skip restoring fpexc32 for AArch64 guests */
> if (!(read_sysreg(hcr_el2) & HCR_RW))
> write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2],
> fpexc32_el2);
> +
> + vcpu->arch.flags |= KVM_ARM64_FP_ENABLED;
> }
>
> /*
> @@ -418,7 +429,6 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> {
> struct kvm_cpu_context *host_ctxt;
> struct kvm_cpu_context *guest_ctxt;
> - bool fp_enabled;
> u64 exit_code;
>
> host_ctxt = vcpu->arch.host_cpu_context;
> @@ -440,19 +450,14 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> /* And we're baaack! */
> } while (fixup_guest_exit(vcpu, &exit_code));
>
> - fp_enabled = fpsimd_enabled_vhe();
> -
> sysreg_save_guest_state_vhe(guest_ctxt);
>
> __deactivate_traps(vcpu);
>
> sysreg_restore_host_state_vhe(host_ctxt);
>
> - if (fp_enabled) {
> - __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
> - __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs);
> + if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
> __fpsimd_save_fpexc32(vcpu);
> - }
>
> __debug_switch_to_host(vcpu);
>
> @@ -464,7 +469,6 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
> {
> struct kvm_cpu_context *host_ctxt;
> struct kvm_cpu_context *guest_ctxt;
> - bool fp_enabled;
> u64 exit_code;
>
> vcpu = kern_hyp_va(vcpu);
> @@ -496,8 +500,6 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
> /* And we're baaack! */
> } while (fixup_guest_exit(vcpu, &exit_code));
>
> - fp_enabled = __fpsimd_enabled_nvhe();
> -
> __sysreg_save_state_nvhe(guest_ctxt);
> __sysreg32_save_state(vcpu);
> __timer_disable_traps(vcpu);
> @@ -508,11 +510,8 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
>
> __sysreg_restore_state_nvhe(host_ctxt);
>
> - if (fp_enabled) {
> - __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
> - __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs);
> + if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
> __fpsimd_save_fpexc32(vcpu);
> - }
>
> /*
> * This must come after restoring the host sysregs, since a non-VHE
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index a4c1b76..bee226c 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -363,10 +363,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
> kvm_vgic_load(vcpu);
> kvm_timer_vcpu_load(vcpu);
> kvm_vcpu_load_sysregs(vcpu);
> + kvm_arch_vcpu_load_fp(vcpu);
> }
>
> void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
> {
> + kvm_arch_vcpu_put_fp(vcpu);
> kvm_vcpu_put_sysregs(vcpu);
> kvm_timer_vcpu_put(vcpu);
> kvm_vgic_put(vcpu);
> @@ -778,6 +780,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
> if (static_branch_unlikely(&userspace_irqchip_in_use))
> kvm_timer_sync_hwstate(vcpu);
>
> + kvm_arch_vcpu_ctxsync_fp(vcpu);
> +
> /*
> * We may have taken a host interrupt in HYP mode (ie
> * while executing the guest). This interrupt is still
Minor bike-shedding aside:
Reviewed-by: Alex Benn?e <alex.bennee@linaro.org>
--
Alex Benn?e
^ permalink raw reply
* [PATCH v10 07/18] arm64: fpsimd: Eliminate task->mm checks
From: Christoffer Dall @ 2018-05-24 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524095056.GR13470@e103592.cambridge.arm.com>
On Thu, May 24, 2018 at 10:50:56AM +0100, Dave Martin wrote:
> On Thu, May 24, 2018 at 10:33:50AM +0200, Christoffer Dall wrote:
> > On Wed, May 23, 2018 at 04:03:37PM +0100, Dave Martin wrote:
> > > On Wed, May 23, 2018 at 03:56:57PM +0100, Catalin Marinas wrote:
> > > > On Wed, May 23, 2018 at 02:31:59PM +0100, Dave P Martin wrote:
> > > > > On Wed, May 23, 2018 at 01:48:12PM +0200, Christoffer Dall wrote:
> > > > > > On Tue, May 22, 2018 at 05:05:08PM +0100, Dave Martin wrote:
> > > > > > > This is true by construction however: TIF_FOREIGN_FPSTATE is never
> > > > > > > cleared except when returning to userspace or returning from a
> > > > > > > signal: thus, for a true kernel thread no FPSIMD context is ever
> > > > > > > loaded, TIF_FOREIGN_FPSTATE will remain set and no context will
> > > > > > > ever be saved.
> > > > > >
> > > > > > I don't understand this construction proof; from looking at the patch
> > > > > > below it is not obvious to me why fpsimd_thread_switch() can never have
> > > > > > !wrong_task && !wrong_cpu and therefore clear TIF_FOREIGN_FPSTATE for a
> > > > > > kernel thread?
> > > > >
> > > > > Looking at this again, I think it is poorly worded. This patch aims to
> > > > > make it true by construction, but it isn't prior to the patch.
> > > > >
> > > > > I'm tempted to delete the paragraph: the assertion of both untrue and
> > > > > not the best way to justify that this patch works.
> > > > >
> > > > >
> > > > > How about:
> > > > >
> > > > > -8<-
> > > > >
> > > > > The context switch logic already isolates user threads from each other.
> > > > > This, it is sufficient for isolating user threads from the kernel,
> >
> > s/This/Thus/ ?
> >
> > I don't understand what 'it' refers to here?
> >
> > > > > since the goal either way is to ensure that code executing in userspace
> > > > > cannot see any FPSIMD state except its own. Thus, there is no special
> > > > > property of kernel threads that we care about except that it is
> > > > > pointless to save or load FPSIMD register state for them.
> >
> > Actually, I'm not really sure what this paragraph is getting at.
>
> Reading this again, I don't think the paragraph adds much useful.
>
> So I propose deleting that too.
>
> > > > >
> > > > > At worst, the removal of all the kernel thread special cases by this
> > > > > patch would thus spuriously load and save state for kernel threads when
> > > > > unnecessary.
> > > > >
> > > > > But the context switch logic is already deliberately optimised to defer
> > > > > reloads of the regs until ret_to_user (or sigreturn as a special case),
> > > > > which kernel threads by definition never reach.
> > > > >
> > > > > ->8-
> > > >
> > > > The "at worst" paragraph makes it look like it could happen (at least
> > > > until you reach the last paragraph). Maybe you can just say that
> > > > wrong_task and wrong_cpu (with the fpsimd_cpu = NR_CPUS addition) are
> > > > always true for kernel threads. You should probably mention this in a
> > > > comment in the code as well.
> > >
> > > What if I just delete the second paragraph, and remove the "But" from
> > > the start of the third, and append:
> > >
> > > "As a result, the wrong_task and wrong_cpu tests in
> > > fpsimd_thread_switch() will always yield false for kernel threads."
> > >
> > > ...with a similar comment in the code?
> >
> > ...with a risk of being a bit over-pedantic and annoying, may I suggest
> > the following complete commit text:
> >
> > ------8<------
> > Currently the FPSIMD handling code uses the condition task->mm ==
> > NULL as a hint that task has no FPSIMD register context.
> >
> > The ->mm check is only there to filter out tasks that cannot
> > possibly have FPSIMD context loaded, for optimisation purposes.
> > However, TIF_FOREIGN_FPSTATE must always be checked anyway before
> > saving FPSIMD context back to memory. For this reason, the ->mm
> > checks are not useful, providing that that TIF_FOREIGN_FPSTATE is
> > maintained properly for kernel threads.
> >
> > FPSIMD context is never preserved for kernel threads across a context
> > switch and therefore TIF_FOREIGN_FPSTATE should always be true for
>
> (This refactoring opens up the interesting possibility of making
> kernel-mode NEON in task context preemptible for kernel threads so
> that we actually do preserve state... but that's a discussion for
> another day. There may be code around that relies on
> kernel_neon_begin() disabling preemption for real.)
>
> > kernel threads. This is indeed the case, as the wrong_task and
>
> This suggests that TIF_FOREIGN_FPSTATE is always true for kernel
> threads today. This is not quite because use_mm() can make mm non-
> NULL.
>
I was suggesting that it's always true after this patch.
> > wrong_cpu tests in fpsimd_thread_switch() will always yield false for
> > kernel threads.
>
> ("false" -> "true". My bad.)
>
> > Further, the context switch logic is already deliberately optimised to
> > defer reloads of the FPSIMD context until ret_to_user (or sigreturn as a
> > special case), which kernel threads by definition never reach, and
> > therefore this change introduces no additional work in the critical
> > path.
> >
> > This patch removes the redundant checks and special-case code.
> > ------8<------
>
> Looking at my existing text, I rather reworded it like this.
> Does this work any better for you?
>
> --8<--
>
> Currently the FPSIMD handling code uses the condition task->mm ==
> NULL as a hint that task has no FPSIMD register context.
>
> The ->mm check is only there to filter out tasks that cannot
> possibly have FPSIMD context loaded, for optimisation purposes.
> Also, TIF_FOREIGN_FPSTATE must always be checked anyway before
> saving FPSIMD context back to memory. For these reasons, the ->mm
> checks are not useful, providing that TIF_FOREIGN_FPSTATE is
> maintained in a consistent way for kernel threads.
Consistent with what? Without more context or explanation,
I'm not sure what the reader is to make of that. Do you not mean the
TIF_FOREIGN_FPSTATE is always true for kernel threads?
>
> The context switch logic is already deliberately optimised to defer
> reloads of the regs until ret_to_user (or sigreturn as a special
> case), and save them only if they have been previously loaded.
> Kernel threads by definition never reach these paths. As a result,
I'm struggling with the "As a result," here. Is this because reloads of
regs in ret_to_user (or sigreturn) are the only places that can make
wrong_cpu or wrong_task be false?
(I'm actually wanting to understand this, not just bikeshedding the
commit message, as new corner cases keep coming up on this logic.)
> the wrong_task and wrong_cpu tests in fpsimd_thread_switch() will
> always yield true for kernel threads.
>
> This patch removes the redundant checks and special-case code, ensuring that TIF_FOREIGN_FPSTATE is set whenever a kernel thread is scheduled in, and ensures that this flag is set for the init
> task. The fpsimd_flush_task_state() call already present in copy_thread() ensures the same for any new task.
nit: funny formatting
nit: ensuring that TIF_FOREIGN_FPSTATE *remains* set whenever a kernel
thread is scheduled in?
>
> With TIF_FOREIGN_FPSTATE always set for kernel threads, this patch
> ensures that no extra context save work is added for kernel
> threads, and eliminates the redundant context saving that may
> currently occur for kernel threads that have acquired an mm via
> use_mm().
>
> -->8--
If you can slightly connect the dots with the "As a result" above, I'm
fine with your version of the text.
Thanks,
-Christoffer
^ permalink raw reply
* [PATCH v10 04/18] KVM: arm/arm64: Introduce kvm_arch_vcpu_run_pid_change
From: Dave Martin @ 2018-05-24 10:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87d0xltnrk.fsf@linaro.org>
On Thu, May 24, 2018 at 10:18:39AM +0100, Alex Benn?e wrote:
>
> Christoffer Dall <christoffer.dall@arm.com> writes:
>
> > On Wed, May 23, 2018 at 03:40:26PM +0100, Dave Martin wrote:
> >> On Wed, May 23, 2018 at 03:34:20PM +0100, Alex Benn?e wrote:
> >> >
> >> > Dave Martin <Dave.Martin@arm.com> writes:
[...]
> >> > > diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
> >> > > index cca7e06..72143cf 100644
> >> > > --- a/virt/kvm/Kconfig
> >> > > +++ b/virt/kvm/Kconfig
> >> > > @@ -54,3 +54,6 @@ config HAVE_KVM_IRQ_BYPASS
> >> > >
> >> > > config HAVE_KVM_VCPU_ASYNC_IOCTL
> >> > > bool
> >> > > +
> >> > > +config HAVE_KVM_VCPU_RUN_PID_CHANGE
> >> > > + bool
> >> >
> >> > This almost threw me as I thought you might be able to enable this and
> >> > break the build, but apparently not:
> >> >
> >> > Reviewed-by: Alex Benn?e <alex.bennee@linaro.org>
> >>
> >> Without a "help", the option seems non-interactive and cannot be true
> >> unless something selects it. It seems a bit weird to me too, but the
> >> idiom appears widely used...
> >>
> > Indeed, I've copied this idiom from other things before and nobody has
> > complained, so I think it works (without any further deep insights into
> > the inner workings of Kconfig).
>
> It's fine. My main worry was breaking bisection with the normal "make
> olddefconfig" approach. I tested it and found it to be fine and I don't
> think we need to worry about people adding the symbol to .config
> manually - they get to keep both pieces ;-)
I wasted a fair amount of time at some point in the past trying to work
out why I couldn't set one of these options by
echo CONFIG_FOO=y >>.config ...
That was fun ;)
Cheers
---Dave
^ permalink raw reply
* [PATCH 04/14] arm64: Add ARCH_WORKAROUND_2 probing
From: Suzuki K Poulose @ 2018-05-24 9:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180522150648.28297-5-marc.zyngier@arm.com>
On 22/05/18 16:06, Marc Zyngier wrote:
> As for Spectre variant-2, we rely on SMCCC 1.1 to provide the
> discovery mechanism for detecting the SSBD mitigation.
>
> A new capability is also allocated for that purpose, and a
> config option.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> +static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
> + int scope)
> +{
> + struct arm_smccc_res res;
> + bool supported = true;
> +
> + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
> +
> + if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
> + return false;
> +
> + /*
> + * The probe function return value is either negative
> + * (unsupported or mitigated), positive (unaffected), or zero
> + * (requires mitigation). We only need to do anything in the
> + * last case.
> + */
> + switch (psci_ops.conduit) {
> + case PSCI_CONDUIT_HVC:
> + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> + ARM_SMCCC_ARCH_WORKAROUND_2, &res);
> + if ((int)res.a0 != 0)
> + supported = false;
> + break;
> +
> + case PSCI_CONDUIT_SMC:
> + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> + ARM_SMCCC_ARCH_WORKAROUND_2, &res);
> + if ((int)res.a0 != 0)
> + supported = false;
> + break;
> +
> + default:
> + supported = false;
> + }
> +
> + if (supported) {
> + __this_cpu_write(arm64_ssbd_callback_required, 1);
> + do_ssbd(true);
> + }
Marc,
As discussed, we have minor issue with the "corner case". If a CPU
is hotplugged in which requires the mitigation, after the system has
finalised the cap to "not available", the CPU could go ahead and
do the "work around" as above, while not effectively doing anything
about it at runtime for KVM guests (as thats the only place where
we rely on the CAP being set).
But, yes this is real corner case. There is no easy way to solve it
other than
1) Allow late modifications to CPU hwcaps
OR
2) Penalise the fastpath to always check per-cpu setting.
Regardless,
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
^ permalink raw reply
* [PATCH v10 07/18] arm64: fpsimd: Eliminate task->mm checks
From: Dave Martin @ 2018-05-24 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524083350.GK55598@C02W217FHV2R.local>
On Thu, May 24, 2018 at 10:33:50AM +0200, Christoffer Dall wrote:
> On Wed, May 23, 2018 at 04:03:37PM +0100, Dave Martin wrote:
> > On Wed, May 23, 2018 at 03:56:57PM +0100, Catalin Marinas wrote:
> > > On Wed, May 23, 2018 at 02:31:59PM +0100, Dave P Martin wrote:
> > > > On Wed, May 23, 2018 at 01:48:12PM +0200, Christoffer Dall wrote:
> > > > > On Tue, May 22, 2018 at 05:05:08PM +0100, Dave Martin wrote:
> > > > > > This is true by construction however: TIF_FOREIGN_FPSTATE is never
> > > > > > cleared except when returning to userspace or returning from a
> > > > > > signal: thus, for a true kernel thread no FPSIMD context is ever
> > > > > > loaded, TIF_FOREIGN_FPSTATE will remain set and no context will
> > > > > > ever be saved.
> > > > >
> > > > > I don't understand this construction proof; from looking at the patch
> > > > > below it is not obvious to me why fpsimd_thread_switch() can never have
> > > > > !wrong_task && !wrong_cpu and therefore clear TIF_FOREIGN_FPSTATE for a
> > > > > kernel thread?
> > > >
> > > > Looking at this again, I think it is poorly worded. This patch aims to
> > > > make it true by construction, but it isn't prior to the patch.
> > > >
> > > > I'm tempted to delete the paragraph: the assertion of both untrue and
> > > > not the best way to justify that this patch works.
> > > >
> > > >
> > > > How about:
> > > >
> > > > -8<-
> > > >
> > > > The context switch logic already isolates user threads from each other.
> > > > This, it is sufficient for isolating user threads from the kernel,
>
> s/This/Thus/ ?
>
> I don't understand what 'it' refers to here?
>
> > > > since the goal either way is to ensure that code executing in userspace
> > > > cannot see any FPSIMD state except its own. Thus, there is no special
> > > > property of kernel threads that we care about except that it is
> > > > pointless to save or load FPSIMD register state for them.
>
> Actually, I'm not really sure what this paragraph is getting at.
Reading this again, I don't think the paragraph adds much useful.
So I propose deleting that too.
> > > >
> > > > At worst, the removal of all the kernel thread special cases by this
> > > > patch would thus spuriously load and save state for kernel threads when
> > > > unnecessary.
> > > >
> > > > But the context switch logic is already deliberately optimised to defer
> > > > reloads of the regs until ret_to_user (or sigreturn as a special case),
> > > > which kernel threads by definition never reach.
> > > >
> > > > ->8-
> > >
> > > The "at worst" paragraph makes it look like it could happen (at least
> > > until you reach the last paragraph). Maybe you can just say that
> > > wrong_task and wrong_cpu (with the fpsimd_cpu = NR_CPUS addition) are
> > > always true for kernel threads. You should probably mention this in a
> > > comment in the code as well.
> >
> > What if I just delete the second paragraph, and remove the "But" from
> > the start of the third, and append:
> >
> > "As a result, the wrong_task and wrong_cpu tests in
> > fpsimd_thread_switch() will always yield false for kernel threads."
> >
> > ...with a similar comment in the code?
>
> ...with a risk of being a bit over-pedantic and annoying, may I suggest
> the following complete commit text:
>
> ------8<------
> Currently the FPSIMD handling code uses the condition task->mm ==
> NULL as a hint that task has no FPSIMD register context.
>
> The ->mm check is only there to filter out tasks that cannot
> possibly have FPSIMD context loaded, for optimisation purposes.
> However, TIF_FOREIGN_FPSTATE must always be checked anyway before
> saving FPSIMD context back to memory. For this reason, the ->mm
> checks are not useful, providing that that TIF_FOREIGN_FPSTATE is
> maintained properly for kernel threads.
>
> FPSIMD context is never preserved for kernel threads across a context
> switch and therefore TIF_FOREIGN_FPSTATE should always be true for
(This refactoring opens up the interesting possibility of making
kernel-mode NEON in task context preemptible for kernel threads so
that we actually do preserve state... but that's a discussion for
another day. There may be code around that relies on
kernel_neon_begin() disabling preemption for real.)
> kernel threads. This is indeed the case, as the wrong_task and
This suggests that TIF_FOREIGN_FPSTATE is always true for kernel
threads today. This is not quite because use_mm() can make mm non-
NULL.
> wrong_cpu tests in fpsimd_thread_switch() will always yield false for
> kernel threads.
("false" -> "true". My bad.)
> Further, the context switch logic is already deliberately optimised to
> defer reloads of the FPSIMD context until ret_to_user (or sigreturn as a
> special case), which kernel threads by definition never reach, and
> therefore this change introduces no additional work in the critical
> path.
>
> This patch removes the redundant checks and special-case code.
> ------8<------
Looking@my existing text, I rather reworded it like this.
Does this work any better for you?
--8<--
Currently the FPSIMD handling code uses the condition task->mm ==
NULL as a hint that task has no FPSIMD register context.
The ->mm check is only there to filter out tasks that cannot
possibly have FPSIMD context loaded, for optimisation purposes.
Also, TIF_FOREIGN_FPSTATE must always be checked anyway before
saving FPSIMD context back to memory. For these reasons, the ->mm
checks are not useful, providing that TIF_FOREIGN_FPSTATE is
maintained in a consistent way for kernel threads.
The context switch logic is already deliberately optimised to defer
reloads of the regs until ret_to_user (or sigreturn as a special
case), and save them only if they have been previously loaded.
Kernel threads by definition never reach these paths. As a result,
the wrong_task and wrong_cpu tests in fpsimd_thread_switch() will
always yield true for kernel threads.
This patch removes the redundant checks and special-case code, ensuring that TIF_FOREIGN_FPSTATE is set whenever a kernel thread is scheduled in, and ensures that this flag is set for the init
task. The fpsimd_flush_task_state() call already present in copy_thread() ensures the same for any new task.
With TIF_FOREIGN_FPSTATE always set for kernel threads, this patch
ensures that no extra context save work is added for kernel
threads, and eliminates the redundant context saving that may
currently occur for kernel threads that have acquired an mm via
use_mm().
-->8--
Cheers
---Dave
^ permalink raw reply
* v4.17-rc1: regressions on N900, N950
From: Pavel Machek @ 2018-05-24 9:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180523220456.GY98604@atomide.com>
Hi!
> > > So... I did some experiments on v4.16.
> > >
> > > Swapping tsc2005 at 0 and lcd: acx565akm at 2 entries in the dts does break
> > > stuff.
> > >
> > > I thought it might be due to vio regulator, but it does not appear
> > > so... screen still works with tsc2005 driver disabled in .config. (so
> > > there's noone to enable vio regulator).
> >
> > Deleting tsc2005 at 0 entry also breaks screen.
> >
> > Replacing tsc2005 at 0 entry with
> >
> > foobar at 0 {
> > compatible = "not really with anything";
> > spi-max-frequency = <6000000>;
> > reg = <0>;
> > };
> >
> > still results in working touchscreen, removing any of the three fields
> > breaks it again.
>
> I bisected one regression down, see "omapdrm regression in v4.17-rc series"
> not sure if it covers all the issues being discussed here though.
Reverting 24aac6011f70 fixes screen on n900 in v4.17-rc for me. (But
strange dependency on tsc2005 at 0 is still there).
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180524/ce0bf288/attachment.sig>
^ permalink raw reply
* [PATCH v10 06/18] arm64: fpsimd: Generalise context saving for non-task contexts
From: Alex Bennée @ 2018-05-24 9:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524090322.GQ13470@e103592.cambridge.arm.com>
Dave Martin <Dave.Martin@arm.com> writes:
> On Wed, May 23, 2018 at 09:15:11PM +0100, Alex Benn?e wrote:
>>
>> Dave Martin <Dave.Martin@arm.com> writes:
>>
>> > In preparation for allowing non-task (i.e., KVM vcpu) FPSIMD
>> > contexts to be handled by the fpsimd common code, this patch adapts
>> > task_fpsimd_save() to save back the currently loaded context,
>> > removing the explicit dependency on current.
>> >
>> > The relevant storage to write back to in memory is now found by
>> > examining the fpsimd_last_state percpu struct.
>> >
>> > fpsimd_save() does nothing unless TIF_FOREIGN_FPSTATE is clear, and
>> > fpsimd_last_state is updated under local_bh_disable() or
>> > local_irq_disable() everywhere that TIF_FOREIGN_FPSTATE is cleared:
>> > thus, fpsimd_save() will write back to the correct storage for the
>> > loaded context.
>> >
>> > No functional change.
>> >
>> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>> > Acked-by: Marc Zyngier <marc.zyngier@arm.com>
>> > Acked-by: Catalin Marinas <catalin.marinas@arm.com>
>> > ---
>> > arch/arm64/kernel/fpsimd.c | 25 +++++++++++++------------
>> > 1 file changed, 13 insertions(+), 12 deletions(-)
>> >
>> > diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
>> > index 9d85373..3aa100a 100644
>> > --- a/arch/arm64/kernel/fpsimd.c
>> > +++ b/arch/arm64/kernel/fpsimd.c
>> > @@ -270,13 +270,15 @@ static void task_fpsimd_load(void)
>> > }
>> >
>> > /*
>> > - * Ensure current's FPSIMD/SVE storage in thread_struct is up to date
>> > - * with respect to the CPU registers.
>> > + * Ensure FPSIMD/SVE storage in memory for the loaded context is up to
>> > + * date with respect to the CPU registers.
>> > *
>> > * Softirqs (and preemption) must be disabled.
>> > */
>> > -static void task_fpsimd_save(void)
>> > +static void fpsimd_save(void)
>> > {
>> > + struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st);
>> > +
>>
>> I thought I was missing something but the only write I saw of this was:
>>
>> __this_cpu_write(fpsimd_last_state.st, NULL);
>>
>> which implied to me it is possible to have an invalid de-reference. I
>> did figure it out eventually as fpsimd_bind_state_to_cpu uses a more
>> indirect this_cpu_ptr idiom for tweaking this. I guess a reference to
>> fpsimd_bind_[task|state]_to_cpu in the comment would have helped my
>> confusion.
>
> How about:
>
> static void fpsimd_save(void)
> {
> struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st);
> + /* set by fpsimd_bind_to_cpu() */
Great, thanks ;-)
--
Alex Benn?e
^ permalink raw reply
* [PATCH 4.16 090/161] staging: bcm2835-audio: Release resources on module_exit()
From: Greg Kroah-Hartman @ 2018-05-24 9:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524093018.331893860@linuxfoundation.org>
4.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kirill Marinushkin <k.marinushkin@gmail.com>
[ Upstream commit 626118b472d2eb45f83a0276a18d3e6a01c69f6a ]
In the current implementation, `rmmod snd_bcm2835` does not release
resources properly. It causes an oops when trying to list sound devices.
This commit fixes it.
The details WRT allocation / free are described below.
Device structure WRT allocation:
pdev
\childdev[]
\card
\chip
\pcm
\ctl
Allocation / register sequence:
* childdev: devm_kzalloc - freed during driver detach
* childdev: device_initialize - freed during device_unregister
* pdev: devres_alloc - freed during driver detach
* childdev: device_add - removed during device_unregister
* pdev, childdev: devres_add - freed during driver detach
* card: snd_card_new - freed during snd_card_free
* chip: kzalloc - freed during kfree
* card, chip: snd_device_new - freed during snd_device_free
* chip: new_pcm - TODO: free pcm
* chip: new_ctl - TODO: free ctl
* card: snd_card_register - unregistered during snd_card_free
Free / unregister sequence:
* card: snd_card_free
* card, chip: snd_device_free
* childdev: device_unregister
* chip: kfree
Steps to reproduce the issue before this commit:
~~~~
$ rmmod snd_bcm2835
$ aplay -L
[ 138.648130] Unable to handle kernel paging request at virtual address 7f1343c0
[ 138.660415] pgd = ad8f0000
[ 138.665567] [7f1343c0] *pgd=3864c811, *pte=00000000, *ppte=00000000
[ 138.674887] Internal error: Oops: 7 [#1] SMP ARM
[ 138.683571] Modules linked in: sha256_generic cfg80211 rfkill snd_pcm snd_timer
snd fixed uio_pdrv_genirq uio ip_tables x_tables ipv6 [last unloaded: snd_bcm2835
]
[ 138.706594] CPU: 3 PID: 463 Comm: aplay Tainted: G WC 4.15.0-rc1-v
7+ #6
[ 138.719833] Hardware name: BCM2835
[ 138.726016] task: b877ac00 task.stack: aebec000
[ 138.733408] PC is at try_module_get+0x38/0x24c
[ 138.740813] LR is at snd_ctl_open+0x58/0x194 [snd]
[ 138.748485] pc : [<801c4d5c>] lr : [<7f0e6b2c>] psr: 20000013
[ 138.757709] sp : aebedd60 ip : aebedd88 fp : aebedd84
[ 138.765884] r10: 00000000 r9 : 00000004 r8 : 7f0ed440
[ 138.774040] r7 : b7e469b0 r6 : 7f0e6b2c r5 : afd91900 r4 : 7f1343c0
[ 138.783571] r3 : aebec000 r2 : 00000001 r1 : b877ac00 r0 : 7f1343c0
[ 138.793084] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 138.803300] Control: 10c5387d Table: 2d8f006a DAC: 00000055
[ 138.812064] Process aplay (pid: 463, stack limit = 0xaebec210)
[ 138.820868] Stack: (0xaebedd60 to 0xaebee000)
[ 138.828207] dd60: 00000000 b848d000 afd91900 00000000 b7e469b0 7f0ed440 aebedda4 aebedd88
[ 138.842371] dd80: 7f0e6b2c 801c4d30 afd91900 7f0ea4dc 00000000 b7e469b0 aebeddcc aebedda8
[ 138.856611] dda0: 7f0e250c 7f0e6ae0 7f0e2464 b8478ec0 b7e469b0 afd91900 7f0ea388 00000000
[ 138.870864] ddc0: aebeddf4 aebeddd0 802ce590 7f0e2470 8090ab64 afd91900 afd91900 b7e469b0
[ 138.885301] dde0: afd91908 802ce4e4 aebede1c aebeddf8 802c57b4 802ce4f0 afd91900 aebedea8
[ 138.900110] de00: b7fa4c00 00000000 00000000 00000004 aebede3c aebede20 802c6ba8 802c56b4
[ 138.915260] de20: aebedea8 00000000 aebedf5c 00000000 aebedea4 aebede40 802d9a68 802c6b58
[ 138.930661] de40: b874ddd0 00000000 00000000 00000001 00000041 00000000 afd91900 aebede70
[ 138.946402] de60: 00000000 00000000 00000002 b7e469b0 b8a87610 b8d6ab80 801852f8 00080000
[ 138.962314] de80: aebedf5c aebedea8 00000001 80108464 aebec000 00000000 aebedf4c aebedea8
[ 138.978414] dea0: 802dacd4 802d970c b8a87610 b8d6ab80 a7982bc6 00000009 af363019 b9231480
[ 138.994617] dec0: 00000000 b8c038a0 b7e469b0 00000101 00000002 00000238 00000000 00000000
[ 139.010823] dee0: 00000000 aebedee8 00080000 0000000f aebedf3c aebedf00 802ed7e4 80843f94
[ 139.027025] df00: 00000003 00080000 b9231490 b9231480 00000000 00080000 af363000 00000000
[ 139.043229] df20: 00000005 00000002 ffffff9c 00000000 00080000 ffffff9c af363000 00000003
[ 139.059430] df40: aebedf94 aebedf50 802c6f70 802dac70 aebec000 00000000 00000001 00000000
[ 139.075629] df60: 00020000 00000004 00000100 00000001 7ebe577c 0002e038 00000000 00000005
[ 139.091828] df80: 80108464 aebec000 aebedfa4 aebedf98 802c7060 802c6e6c 00000000 aebedfa8
[ 139.108025] dfa0: 801082c0 802c7040 7ebe577c 0002e038 7ebe577c 00080000 00000b98 e81c8400
[ 139.124222] dfc0: 7ebe577c 0002e038 00000000 00000005 7ebe57e4 00a20af8 7ebe57f0 76f87394
[ 139.140419] dfe0: 00000000 7ebe55c4 76ec88e8 76df1d9c 60000010 7ebe577c 00000000 00000000
[ 139.156715] [<801c4d5c>] (try_module_get) from [<7f0e6b2c>] (snd_ctl_open+0x58/0x194 [snd])
[ 139.173222] [<7f0e6b2c>] (snd_ctl_open [snd]) from [<7f0e250c>] (snd_open+0xa8/0x14c [snd])
[ 139.189683] [<7f0e250c>] (snd_open [snd]) from [<802ce590>] (chrdev_open+0xac/0x188)
[ 139.205465] [<802ce590>] (chrdev_open) from [<802c57b4>] (do_dentry_open+0x10c/0x314)
[ 139.221347] [<802c57b4>] (do_dentry_open) from [<802c6ba8>] (vfs_open+0x5c/0x88)
[ 139.236788] [<802c6ba8>] (vfs_open) from [<802d9a68>] (path_openat+0x368/0x944)
[ 139.248270] [<802d9a68>] (path_openat) from [<802dacd4>] (do_filp_open+0x70/0xc4)
[ 139.263731] [<802dacd4>] (do_filp_open) from [<802c6f70>] (do_sys_open+0x110/0x1d4)
[ 139.279378] [<802c6f70>] (do_sys_open) from [<802c7060>] (SyS_open+0x2c/0x30)
[ 139.290647] [<802c7060>] (SyS_open) from [<801082c0>] (ret_fast_syscall+0x0/0x28)
[ 139.306021] Code: e3c3303f e5932004 e2822001 e5832004 (e5943000)
[ 139.316265] ---[ end trace 7f3f7f6193b663ed ]---
[ 139.324956] note: aplay[463] exited with preempt_count 1
~~~~
Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Ray Jui <rjui@broadcom.com>
Cc: Scott Branden <sbranden@broadcom.com>
Cc: bcm-kernel-feedback-list at broadcom.com
Cc: Michael Zoran <mzoran@crowfest.net>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: linux-rpi-kernel at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: devel at driverdev.osuosl.org
Cc: linux-kernel at vger.kernel.org
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 54 ++++++++----------
1 file changed, 25 insertions(+), 29 deletions(-)
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
@@ -25,6 +25,10 @@ MODULE_PARM_DESC(enable_compat_alsa,
static void snd_devm_unregister_child(struct device *dev, void *res)
{
struct device *childdev = *(struct device **)res;
+ struct bcm2835_chip *chip = dev_get_drvdata(childdev);
+ struct snd_card *card = chip->card;
+
+ snd_card_free(card);
device_unregister(childdev);
}
@@ -50,6 +54,13 @@ static int snd_devm_add_child(struct dev
return 0;
}
+static void snd_bcm2835_release(struct device *dev)
+{
+ struct bcm2835_chip *chip = dev_get_drvdata(dev);
+
+ kfree(chip);
+}
+
static struct device *
snd_create_device(struct device *parent,
struct device_driver *driver,
@@ -65,6 +76,7 @@ snd_create_device(struct device *parent,
device_initialize(device);
device->parent = parent;
device->driver = driver;
+ device->release = snd_bcm2835_release;
dev_set_name(device, "%s", name);
@@ -75,18 +87,19 @@ snd_create_device(struct device *parent,
return device;
}
-static int snd_bcm2835_free(struct bcm2835_chip *chip)
-{
- kfree(chip);
- return 0;
-}
-
/* component-destructor
* (see "Management of Cards and Components")
*/
static int snd_bcm2835_dev_free(struct snd_device *device)
{
- return snd_bcm2835_free(device->device_data);
+ struct bcm2835_chip *chip = device->device_data;
+ struct snd_card *card = chip->card;
+
+ /* TODO: free pcm, ctl */
+
+ snd_device_free(card, chip);
+
+ return 0;
}
/* chip-specific constructor
@@ -111,7 +124,7 @@ static int snd_bcm2835_create(struct snd
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err) {
- snd_bcm2835_free(chip);
+ kfree(chip);
return err;
}
@@ -119,31 +132,14 @@ static int snd_bcm2835_create(struct snd
return 0;
}
-static void snd_devm_card_free(struct device *dev, void *res)
+static struct snd_card *snd_bcm2835_card_new(struct device *dev)
{
- struct snd_card *snd_card = *(struct snd_card **)res;
-
- snd_card_free(snd_card);
-}
-
-static struct snd_card *snd_devm_card_new(struct device *dev)
-{
- struct snd_card **dr;
struct snd_card *card;
int ret;
- dr = devres_alloc(snd_devm_card_free, sizeof(*dr), GFP_KERNEL);
- if (!dr)
- return ERR_PTR(-ENOMEM);
-
ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
- if (ret) {
- devres_free(dr);
+ if (ret)
return ERR_PTR(ret);
- }
-
- *dr = card;
- devres_add(dev, dr);
return card;
}
@@ -260,7 +256,7 @@ static int snd_add_child_device(struct d
return PTR_ERR(child);
}
- card = snd_devm_card_new(child);
+ card = snd_bcm2835_card_new(child);
if (IS_ERR(card)) {
dev_err(child, "Failed to create card");
return PTR_ERR(card);
@@ -302,7 +298,7 @@ static int snd_add_child_device(struct d
return err;
}
- dev_set_drvdata(child, card);
+ dev_set_drvdata(child, chip);
dev_info(child, "card created with %d channels\n", numchans);
return 0;
^ permalink raw reply
* [PATCH 4.14 085/165] staging: bcm2835-audio: Release resources on module_exit()
From: Greg Kroah-Hartman @ 2018-05-24 9:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524093621.979359379@linuxfoundation.org>
4.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kirill Marinushkin <k.marinushkin@gmail.com>
[ Upstream commit 626118b472d2eb45f83a0276a18d3e6a01c69f6a ]
In the current implementation, `rmmod snd_bcm2835` does not release
resources properly. It causes an oops when trying to list sound devices.
This commit fixes it.
The details WRT allocation / free are described below.
Device structure WRT allocation:
pdev
\childdev[]
\card
\chip
\pcm
\ctl
Allocation / register sequence:
* childdev: devm_kzalloc - freed during driver detach
* childdev: device_initialize - freed during device_unregister
* pdev: devres_alloc - freed during driver detach
* childdev: device_add - removed during device_unregister
* pdev, childdev: devres_add - freed during driver detach
* card: snd_card_new - freed during snd_card_free
* chip: kzalloc - freed during kfree
* card, chip: snd_device_new - freed during snd_device_free
* chip: new_pcm - TODO: free pcm
* chip: new_ctl - TODO: free ctl
* card: snd_card_register - unregistered during snd_card_free
Free / unregister sequence:
* card: snd_card_free
* card, chip: snd_device_free
* childdev: device_unregister
* chip: kfree
Steps to reproduce the issue before this commit:
~~~~
$ rmmod snd_bcm2835
$ aplay -L
[ 138.648130] Unable to handle kernel paging request at virtual address 7f1343c0
[ 138.660415] pgd = ad8f0000
[ 138.665567] [7f1343c0] *pgd=3864c811, *pte=00000000, *ppte=00000000
[ 138.674887] Internal error: Oops: 7 [#1] SMP ARM
[ 138.683571] Modules linked in: sha256_generic cfg80211 rfkill snd_pcm snd_timer
snd fixed uio_pdrv_genirq uio ip_tables x_tables ipv6 [last unloaded: snd_bcm2835
]
[ 138.706594] CPU: 3 PID: 463 Comm: aplay Tainted: G WC 4.15.0-rc1-v
7+ #6
[ 138.719833] Hardware name: BCM2835
[ 138.726016] task: b877ac00 task.stack: aebec000
[ 138.733408] PC is at try_module_get+0x38/0x24c
[ 138.740813] LR is at snd_ctl_open+0x58/0x194 [snd]
[ 138.748485] pc : [<801c4d5c>] lr : [<7f0e6b2c>] psr: 20000013
[ 138.757709] sp : aebedd60 ip : aebedd88 fp : aebedd84
[ 138.765884] r10: 00000000 r9 : 00000004 r8 : 7f0ed440
[ 138.774040] r7 : b7e469b0 r6 : 7f0e6b2c r5 : afd91900 r4 : 7f1343c0
[ 138.783571] r3 : aebec000 r2 : 00000001 r1 : b877ac00 r0 : 7f1343c0
[ 138.793084] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 138.803300] Control: 10c5387d Table: 2d8f006a DAC: 00000055
[ 138.812064] Process aplay (pid: 463, stack limit = 0xaebec210)
[ 138.820868] Stack: (0xaebedd60 to 0xaebee000)
[ 138.828207] dd60: 00000000 b848d000 afd91900 00000000 b7e469b0 7f0ed440 aebedda4 aebedd88
[ 138.842371] dd80: 7f0e6b2c 801c4d30 afd91900 7f0ea4dc 00000000 b7e469b0 aebeddcc aebedda8
[ 138.856611] dda0: 7f0e250c 7f0e6ae0 7f0e2464 b8478ec0 b7e469b0 afd91900 7f0ea388 00000000
[ 138.870864] ddc0: aebeddf4 aebeddd0 802ce590 7f0e2470 8090ab64 afd91900 afd91900 b7e469b0
[ 138.885301] dde0: afd91908 802ce4e4 aebede1c aebeddf8 802c57b4 802ce4f0 afd91900 aebedea8
[ 138.900110] de00: b7fa4c00 00000000 00000000 00000004 aebede3c aebede20 802c6ba8 802c56b4
[ 138.915260] de20: aebedea8 00000000 aebedf5c 00000000 aebedea4 aebede40 802d9a68 802c6b58
[ 138.930661] de40: b874ddd0 00000000 00000000 00000001 00000041 00000000 afd91900 aebede70
[ 138.946402] de60: 00000000 00000000 00000002 b7e469b0 b8a87610 b8d6ab80 801852f8 00080000
[ 138.962314] de80: aebedf5c aebedea8 00000001 80108464 aebec000 00000000 aebedf4c aebedea8
[ 138.978414] dea0: 802dacd4 802d970c b8a87610 b8d6ab80 a7982bc6 00000009 af363019 b9231480
[ 138.994617] dec0: 00000000 b8c038a0 b7e469b0 00000101 00000002 00000238 00000000 00000000
[ 139.010823] dee0: 00000000 aebedee8 00080000 0000000f aebedf3c aebedf00 802ed7e4 80843f94
[ 139.027025] df00: 00000003 00080000 b9231490 b9231480 00000000 00080000 af363000 00000000
[ 139.043229] df20: 00000005 00000002 ffffff9c 00000000 00080000 ffffff9c af363000 00000003
[ 139.059430] df40: aebedf94 aebedf50 802c6f70 802dac70 aebec000 00000000 00000001 00000000
[ 139.075629] df60: 00020000 00000004 00000100 00000001 7ebe577c 0002e038 00000000 00000005
[ 139.091828] df80: 80108464 aebec000 aebedfa4 aebedf98 802c7060 802c6e6c 00000000 aebedfa8
[ 139.108025] dfa0: 801082c0 802c7040 7ebe577c 0002e038 7ebe577c 00080000 00000b98 e81c8400
[ 139.124222] dfc0: 7ebe577c 0002e038 00000000 00000005 7ebe57e4 00a20af8 7ebe57f0 76f87394
[ 139.140419] dfe0: 00000000 7ebe55c4 76ec88e8 76df1d9c 60000010 7ebe577c 00000000 00000000
[ 139.156715] [<801c4d5c>] (try_module_get) from [<7f0e6b2c>] (snd_ctl_open+0x58/0x194 [snd])
[ 139.173222] [<7f0e6b2c>] (snd_ctl_open [snd]) from [<7f0e250c>] (snd_open+0xa8/0x14c [snd])
[ 139.189683] [<7f0e250c>] (snd_open [snd]) from [<802ce590>] (chrdev_open+0xac/0x188)
[ 139.205465] [<802ce590>] (chrdev_open) from [<802c57b4>] (do_dentry_open+0x10c/0x314)
[ 139.221347] [<802c57b4>] (do_dentry_open) from [<802c6ba8>] (vfs_open+0x5c/0x88)
[ 139.236788] [<802c6ba8>] (vfs_open) from [<802d9a68>] (path_openat+0x368/0x944)
[ 139.248270] [<802d9a68>] (path_openat) from [<802dacd4>] (do_filp_open+0x70/0xc4)
[ 139.263731] [<802dacd4>] (do_filp_open) from [<802c6f70>] (do_sys_open+0x110/0x1d4)
[ 139.279378] [<802c6f70>] (do_sys_open) from [<802c7060>] (SyS_open+0x2c/0x30)
[ 139.290647] [<802c7060>] (SyS_open) from [<801082c0>] (ret_fast_syscall+0x0/0x28)
[ 139.306021] Code: e3c3303f e5932004 e2822001 e5832004 (e5943000)
[ 139.316265] ---[ end trace 7f3f7f6193b663ed ]---
[ 139.324956] note: aplay[463] exited with preempt_count 1
~~~~
Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Ray Jui <rjui@broadcom.com>
Cc: Scott Branden <sbranden@broadcom.com>
Cc: bcm-kernel-feedback-list at broadcom.com
Cc: Michael Zoran <mzoran@crowfest.net>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: linux-rpi-kernel at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: devel at driverdev.osuosl.org
Cc: linux-kernel at vger.kernel.org
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 54 ++++++++----------
1 file changed, 25 insertions(+), 29 deletions(-)
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
@@ -36,6 +36,10 @@ MODULE_PARM_DESC(enable_compat_alsa,
static void snd_devm_unregister_child(struct device *dev, void *res)
{
struct device *childdev = *(struct device **)res;
+ struct bcm2835_chip *chip = dev_get_drvdata(childdev);
+ struct snd_card *card = chip->card;
+
+ snd_card_free(card);
device_unregister(childdev);
}
@@ -61,6 +65,13 @@ static int snd_devm_add_child(struct dev
return 0;
}
+static void snd_bcm2835_release(struct device *dev)
+{
+ struct bcm2835_chip *chip = dev_get_drvdata(dev);
+
+ kfree(chip);
+}
+
static struct device *
snd_create_device(struct device *parent,
struct device_driver *driver,
@@ -76,6 +87,7 @@ snd_create_device(struct device *parent,
device_initialize(device);
device->parent = parent;
device->driver = driver;
+ device->release = snd_bcm2835_release;
dev_set_name(device, "%s", name);
@@ -86,18 +98,19 @@ snd_create_device(struct device *parent,
return device;
}
-static int snd_bcm2835_free(struct bcm2835_chip *chip)
-{
- kfree(chip);
- return 0;
-}
-
/* component-destructor
* (see "Management of Cards and Components")
*/
static int snd_bcm2835_dev_free(struct snd_device *device)
{
- return snd_bcm2835_free(device->device_data);
+ struct bcm2835_chip *chip = device->device_data;
+ struct snd_card *card = chip->card;
+
+ /* TODO: free pcm, ctl */
+
+ snd_device_free(card, chip);
+
+ return 0;
}
/* chip-specific constructor
@@ -122,7 +135,7 @@ static int snd_bcm2835_create(struct snd
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err) {
- snd_bcm2835_free(chip);
+ kfree(chip);
return err;
}
@@ -130,31 +143,14 @@ static int snd_bcm2835_create(struct snd
return 0;
}
-static void snd_devm_card_free(struct device *dev, void *res)
+static struct snd_card *snd_bcm2835_card_new(struct device *dev)
{
- struct snd_card *snd_card = *(struct snd_card **)res;
-
- snd_card_free(snd_card);
-}
-
-static struct snd_card *snd_devm_card_new(struct device *dev)
-{
- struct snd_card **dr;
struct snd_card *card;
int ret;
- dr = devres_alloc(snd_devm_card_free, sizeof(*dr), GFP_KERNEL);
- if (!dr)
- return ERR_PTR(-ENOMEM);
-
ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
- if (ret) {
- devres_free(dr);
+ if (ret)
return ERR_PTR(ret);
- }
-
- *dr = card;
- devres_add(dev, dr);
return card;
}
@@ -271,7 +267,7 @@ static int snd_add_child_device(struct d
return PTR_ERR(child);
}
- card = snd_devm_card_new(child);
+ card = snd_bcm2835_card_new(child);
if (IS_ERR(card)) {
dev_err(child, "Failed to create card");
return PTR_ERR(card);
@@ -313,7 +309,7 @@ static int snd_add_child_device(struct d
return err;
}
- dev_set_drvdata(child, card);
+ dev_set_drvdata(child, chip);
dev_info(child, "card created with %d channels\n", numchans);
return 0;
^ permalink raw reply
* [PATCH 4.4 25/92] futex: Remove duplicated code and fix undefined behaviour
From: Greg Kroah-Hartman @ 2018-05-24 9:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524093159.286472249@linuxfoundation.org>
4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Slaby <jslaby@suse.cz>
commit 30d6e0a4190d37740e9447e4e4815f06992dd8c3 upstream.
There is code duplicated over all architecture's headers for
futex_atomic_op_inuser. Namely op decoding, access_ok check for uaddr,
and comparison of the result.
Remove this duplication and leave up to the arches only the needed
assembly which is now in arch_futex_atomic_op_inuser.
This effectively distributes the Will Deacon's arm64 fix for undefined
behaviour reported by UBSAN to all architectures. The fix was done in
commit 5f16a046f8e1 (arm64: futex: Fix undefined behaviour with
FUTEX_OP_OPARG_SHIFT usage). Look there for an example dump.
And as suggested by Thomas, check for negative oparg too, because it was
also reported to cause undefined behaviour report.
Note that s390 removed access_ok check in d12a29703 ("s390/uaccess:
remove pointless access_ok() checks") as access_ok there returns true.
We introduce it back to the helper for the sake of simplicity (it gets
optimized away anyway).
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> [s390]
Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]
Reviewed-by: Darren Hart (VMware) <dvhart@infradead.org>
Reviewed-by: Will Deacon <will.deacon@arm.com> [core/arm64]
Cc: linux-mips at linux-mips.org
Cc: Rich Felker <dalias@libc.org>
Cc: linux-ia64 at vger.kernel.org
Cc: linux-sh at vger.kernel.org
Cc: peterz at infradead.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: sparclinux at vger.kernel.org
Cc: Jonas Bonn <jonas@southpole.se>
Cc: linux-s390 at vger.kernel.org
Cc: linux-arch at vger.kernel.org
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: linux-hexagon at vger.kernel.org
Cc: Helge Deller <deller@gmx.de>
Cc: "James E.J. Bottomley" <jejb@parisc-linux.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Matt Turner <mattst88@gmail.com>
Cc: linux-snps-arc at lists.infradead.org
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux-xtensa at linux-xtensa.org
Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
Cc: openrisc at lists.librecores.org
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Stafford Horne <shorne@gmail.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: Richard Henderson <rth@twiddle.net>
Cc: Chris Zankel <chris@zankel.net>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-parisc at vger.kernel.org
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Richard Kuo <rkuo@codeaurora.org>
Cc: linux-alpha at vger.kernel.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: linuxppc-dev at lists.ozlabs.org
Cc: "David S. Miller" <davem@davemloft.net>
Link: http://lkml.kernel.org/r/20170824073105.3901-1-jslaby at suse.cz
Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/alpha/include/asm/futex.h | 26 +++---------------
arch/arc/include/asm/futex.h | 40 +++-------------------------
arch/arm/include/asm/futex.h | 26 ++----------------
arch/arm64/include/asm/futex.h | 26 ++----------------
arch/frv/include/asm/futex.h | 3 +-
arch/frv/kernel/futex.c | 27 ++-----------------
arch/hexagon/include/asm/futex.h | 38 ++-------------------------
arch/ia64/include/asm/futex.h | 25 ++----------------
arch/microblaze/include/asm/futex.h | 38 ++-------------------------
arch/mips/include/asm/futex.h | 25 ++----------------
arch/parisc/include/asm/futex.h | 25 ++----------------
arch/powerpc/include/asm/futex.h | 26 +++---------------
arch/s390/include/asm/futex.h | 23 +++-------------
arch/sh/include/asm/futex.h | 26 ++----------------
arch/sparc/include/asm/futex_64.h | 26 +++---------------
arch/tile/include/asm/futex.h | 40 +++-------------------------
arch/x86/include/asm/futex.h | 40 +++-------------------------
arch/xtensa/include/asm/futex.h | 27 +++----------------
include/asm-generic/futex.h | 50 ++++++------------------------------
kernel/futex.c | 39 ++++++++++++++++++++++++++++
20 files changed, 126 insertions(+), 470 deletions(-)
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -29,18 +29,10 @@
: "r" (uaddr), "r"(oparg) \
: "memory")
-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
pagefault_disable();
@@ -66,17 +58,9 @@ static inline int futex_atomic_op_inuser
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/arc/include/asm/futex.h
+++ b/arch/arc/include/asm/futex.h
@@ -73,20 +73,11 @@
#endif
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
- return -EFAULT;
-
#ifndef CONFIG_ARC_HAS_LLSC
preempt_disable(); /* to guarantee atomic r-m-w of futex op */
#endif
@@ -118,30 +109,9 @@ static inline int futex_atomic_op_inuser
preempt_enable();
#endif
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ:
- ret = (oldval == cmparg);
- break;
- case FUTEX_OP_CMP_NE:
- ret = (oldval != cmparg);
- break;
- case FUTEX_OP_CMP_LT:
- ret = (oldval < cmparg);
- break;
- case FUTEX_OP_CMP_GE:
- ret = (oldval >= cmparg);
- break;
- case FUTEX_OP_CMP_LE:
- ret = (oldval <= cmparg);
- break;
- case FUTEX_OP_CMP_GT:
- ret = (oldval > cmparg);
- break;
- default:
- ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -128,20 +128,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
#endif /* !SMP */
static inline int
-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret, tmp;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
#ifndef CONFIG_SMP
preempt_disable();
#endif
@@ -172,17 +162,9 @@ futex_atomic_op_inuser (int encoded_op,
preempt_enable();
#endif
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -53,20 +53,10 @@
: "memory")
static inline int
-futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (int)(encoded_op << 8) >> 20;
- int cmparg = (int)(encoded_op << 20) >> 20;
int oldval = 0, ret, tmp;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1U << (oparg & 0x1f);
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
pagefault_disable();
switch (op) {
@@ -96,17 +86,9 @@ futex_atomic_op_inuser(unsigned int enco
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -7,7 +7,8 @@
#include <asm/errno.h>
#include <asm/uaccess.h>
-extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
+extern int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr);
static inline int
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -186,20 +186,10 @@ static inline int atomic_futex_op_xchg_x
/*
* do the futex operations
*/
-int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
pagefault_disable();
switch (op) {
@@ -225,18 +215,9 @@ int futex_atomic_op_inuser(int encoded_o
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS; break;
- }
- }
+ if (!ret)
+ *oval = oldval;
return ret;
-} /* end futex_atomic_op_inuser() */
+} /* end arch_futex_atomic_op_inuser() */
--- a/arch/hexagon/include/asm/futex.h
+++ b/arch/hexagon/include/asm/futex.h
@@ -31,18 +31,9 @@
static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
- return -EFAULT;
pagefault_disable();
@@ -72,30 +63,9 @@ futex_atomic_op_inuser(int encoded_op, i
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ:
- ret = (oldval == cmparg);
- break;
- case FUTEX_OP_CMP_NE:
- ret = (oldval != cmparg);
- break;
- case FUTEX_OP_CMP_LT:
- ret = (oldval < cmparg);
- break;
- case FUTEX_OP_CMP_GE:
- ret = (oldval >= cmparg);
- break;
- case FUTEX_OP_CMP_LE:
- ret = (oldval <= cmparg);
- break;
- case FUTEX_OP_CMP_GT:
- ret = (oldval > cmparg);
- break;
- default:
- ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -45,18 +45,9 @@ do { \
} while (0)
static inline int
-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
pagefault_disable();
@@ -84,17 +75,9 @@ futex_atomic_op_inuser (int encoded_op,
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -29,18 +29,9 @@
})
static inline int
-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
pagefault_disable();
@@ -66,30 +57,9 @@ futex_atomic_op_inuser(int encoded_op, u
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ:
- ret = (oldval == cmparg);
- break;
- case FUTEX_OP_CMP_NE:
- ret = (oldval != cmparg);
- break;
- case FUTEX_OP_CMP_LT:
- ret = (oldval < cmparg);
- break;
- case FUTEX_OP_CMP_GE:
- ret = (oldval >= cmparg);
- break;
- case FUTEX_OP_CMP_LE:
- ret = (oldval <= cmparg);
- break;
- case FUTEX_OP_CMP_GT:
- ret = (oldval > cmparg);
- break;
- default:
- ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -83,18 +83,9 @@
}
static inline int
-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
pagefault_disable();
@@ -125,17 +116,9 @@ futex_atomic_op_inuser(int encoded_op, u
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -32,20 +32,11 @@ _futex_spin_unlock_irqrestore(u32 __user
}
static inline int
-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{
unsigned long int flags;
u32 val;
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
- return -EFAULT;
pagefault_disable();
@@ -98,17 +89,9 @@ futex_atomic_op_inuser (int encoded_op,
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -31,18 +31,10 @@
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
: "cr0", "memory")
-static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
pagefault_disable();
@@ -68,17 +60,9 @@ static inline int futex_atomic_op_inuser
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -21,17 +21,12 @@
: "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
"m" (*uaddr) : "cc");
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, newval, ret;
load_kernel_asce();
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
pagefault_disable();
switch (op) {
@@ -60,17 +55,9 @@ static inline int futex_atomic_op_inuser
}
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -10,20 +10,11 @@
/* XXX: UP variants, fix for SH-4A and SMP.. */
#include <asm/futex-irq.h>
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
pagefault_disable();
switch (op) {
@@ -49,17 +40,8 @@ static inline int futex_atomic_op_inuser
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
return ret;
}
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -29,22 +29,14 @@
: "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
: "memory")
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret, tem;
- if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
- return -EFAULT;
if (unlikely((((unsigned long) uaddr) & 0x3UL)))
return -EINVAL;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
pagefault_disable();
switch (op) {
@@ -69,17 +61,9 @@ static inline int futex_atomic_op_inuser
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -106,12 +106,9 @@
lock = __atomic_hashed_lock((int __force *)uaddr)
#endif
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int uninitialized_var(val), ret;
__futex_prolog();
@@ -119,12 +116,6 @@ static inline int futex_atomic_op_inuser
/* The 32-bit futex code makes this assumption, so validate it here. */
BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
pagefault_disable();
switch (op) {
case FUTEX_OP_SET:
@@ -148,30 +139,9 @@ static inline int futex_atomic_op_inuser
}
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ:
- ret = (val == cmparg);
- break;
- case FUTEX_OP_CMP_NE:
- ret = (val != cmparg);
- break;
- case FUTEX_OP_CMP_LT:
- ret = (val < cmparg);
- break;
- case FUTEX_OP_CMP_GE:
- ret = (val >= cmparg);
- break;
- case FUTEX_OP_CMP_LE:
- ret = (val <= cmparg);
- break;
- case FUTEX_OP_CMP_GT:
- ret = (val > cmparg);
- break;
- default:
- ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = val;
+
return ret;
}
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -41,20 +41,11 @@
"+m" (*uaddr), "=&r" (tem) \
: "r" (oparg), "i" (-EFAULT), "1" (0))
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret, tem;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
pagefault_disable();
switch (op) {
@@ -80,30 +71,9 @@ static inline int futex_atomic_op_inuser
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ:
- ret = (oldval == cmparg);
- break;
- case FUTEX_OP_CMP_NE:
- ret = (oldval != cmparg);
- break;
- case FUTEX_OP_CMP_LT:
- ret = (oldval < cmparg);
- break;
- case FUTEX_OP_CMP_GE:
- ret = (oldval >= cmparg);
- break;
- case FUTEX_OP_CMP_LE:
- ret = (oldval <= cmparg);
- break;
- case FUTEX_OP_CMP_GT:
- ret = (oldval > cmparg);
- break;
- default:
- ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/arch/xtensa/include/asm/futex.h
+++ b/arch/xtensa/include/asm/futex.h
@@ -44,18 +44,10 @@
: "r" (uaddr), "I" (-EFAULT), "r" (oparg) \
: "memory")
-static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
#if !XCHAL_HAVE_S32C1I
return -ENOSYS;
@@ -89,19 +81,10 @@ static inline int futex_atomic_op_inuser
pagefault_enable();
- if (ret)
- return ret;
-
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: return (oldval == cmparg);
- case FUTEX_OP_CMP_NE: return (oldval != cmparg);
- case FUTEX_OP_CMP_LT: return (oldval < cmparg);
- case FUTEX_OP_CMP_GE: return (oldval >= cmparg);
- case FUTEX_OP_CMP_LE: return (oldval <= cmparg);
- case FUTEX_OP_CMP_GT: return (oldval > cmparg);
- }
+ if (!ret)
+ *oval = oldval;
- return -ENOSYS;
+ return ret;
}
static inline int
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -13,7 +13,7 @@
*/
/**
- * futex_atomic_op_inuser() - Atomic arithmetic operation with constant
+ * arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
* argument and comparison of the previous
* futex value with another constant.
*
@@ -25,18 +25,11 @@
* <0 - On error
*/
static inline int
-futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval, ret;
u32 tmp;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
preempt_disable();
pagefault_disable();
@@ -74,17 +67,9 @@ out_pagefault_enable:
pagefault_enable();
preempt_enable();
- if (ret == 0) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (ret == 0)
+ *oval = oldval;
+
return ret;
}
@@ -126,18 +111,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
#else
static inline int
-futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+arch_futex_atomic_op_inuser(int op, u32 oparg, int *oval, u32 __user *uaddr)
{
- int op = (encoded_op >> 28) & 7;
- int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
int oldval = 0, ret;
- if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
- oparg = 1 << oparg;
-
- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
pagefault_disable();
@@ -153,17 +129,9 @@ futex_atomic_op_inuser (int encoded_op,
pagefault_enable();
- if (!ret) {
- switch (cmp) {
- case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
- case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
- default: ret = -ENOSYS;
- }
- }
+ if (!ret)
+ *oval = oldval;
+
return ret;
}
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1453,6 +1453,45 @@ out:
return ret;
}
+static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
+{
+ unsigned int op = (encoded_op & 0x70000000) >> 28;
+ unsigned int cmp = (encoded_op & 0x0f000000) >> 24;
+ int oparg = sign_extend32((encoded_op & 0x00fff000) >> 12, 12);
+ int cmparg = sign_extend32(encoded_op & 0x00000fff, 12);
+ int oldval, ret;
+
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
+ if (oparg < 0 || oparg > 31)
+ return -EINVAL;
+ oparg = 1 << oparg;
+ }
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+ return -EFAULT;
+
+ ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr);
+ if (ret)
+ return ret;
+
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ:
+ return oldval == cmparg;
+ case FUTEX_OP_CMP_NE:
+ return oldval != cmparg;
+ case FUTEX_OP_CMP_LT:
+ return oldval < cmparg;
+ case FUTEX_OP_CMP_GE:
+ return oldval >= cmparg;
+ case FUTEX_OP_CMP_LE:
+ return oldval <= cmparg;
+ case FUTEX_OP_CMP_GT:
+ return oldval > cmparg;
+ default:
+ return -ENOSYS;
+ }
+}
+
/*
* Wake up all waiters hashed on the physical page that is mapped
* to this virtual address:
^ permalink raw reply
* [PATCH 8/9] PM / Domains: Add support for multi PM domains per device to genpd
From: Jon Hunter @ 2018-05-24 9:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPDyKFo8e5FMrxF2ggxVZ+HQjw4s1Wtx-tMf5ka67knJpZMQcA@mail.gmail.com>
On 24/05/18 08:04, Ulf Hansson wrote:
...
>> Any reason why we could not add a 'boolean' argument to the API to indicate
>> whether the new device should be linked? I think that I prefer the API
>> handles it, but I can see there could be instances where drivers may wish to
>> handle it themselves.
>
> Coming back to this question. Both Tegra XUSB and Qcom Camera use
> case, would benefit from doing the linking themselves, as it needs
> different PM domains to be powered on depending on the current use
> case - as to avoid wasting power.
>
> However, I can understand that you prefer some simplicity over
> optimizations, as you told us. Then, does it mean that you are
> insisting on extending the APIs with a boolean for linking, or are you
> fine with the driver to call device_link_add()?
I am fine with the driver calling device_link_add(), but I just wonder
if we will find a several drivers doing this and then we will end up
doing this later anyway.
The current API is called ...
* genpd_dev_pm_attach_by_id() - Attach a device to one of its PM domain.
* @dev: Device to attach.
* @index: The index of the PM domain.
This naming and description is a bit misleading, because really it is
not attaching the device that is passed, but creating a new device to
attach a PM domain to. So we should consider renaming and changing the
description and indicate that users need to link the device.
Finally, how is a PM domain attached via calling
genpd_dev_pm_attach_by_id() detached?
Cheers
Jon
--
nvpublic
^ permalink raw reply
* [PATCH v2] PM / AVS: rockchip-io: add io selectors and supplies for PX30
From: Rafael J. Wysocki @ 2018-05-24 9:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1899248.qiidGlqZWz@phil>
On Tuesday, May 15, 2018 1:51:26 PM CEST Heiko Stuebner wrote:
> Hi David,
>
> Am Dienstag, 15. Mai 2018, 13:48:19 CEST schrieb David Wu:
> > This adds the necessary data for handling io voltage domains on PX30.
> > As interesting tidbit, the PX30 contains two separate iodomain areas.
> > One in the regular General Register Files (GRF) and one in PMUGRF in the
> > pmu power domain.
> >
> > Signed-off-by: David Wu <david.wu@rock-chips.com>
>
> thanks for the fast respin, looks great now.
>
> Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Applied, thanks!
^ permalink raw reply
* [PATCH v2 05/13] mtd: rawnand: marvell: remove the dmaengine compat need
From: Miquel Raynal @ 2018-05-24 9:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524070703.11901-6-robert.jarzmik@free.fr>
Hi Robert,
On Thu, 24 May 2018 09:06:55 +0200, Robert Jarzmik
<robert.jarzmik@free.fr> wrote:
> As the pxa architecture switched towards the dmaengine slave map, the
> old compatibility mechanism to acquire the dma requestor line number and
> priority are not needed anymore.
>
> This patch simplifies the dma resource acquisition, using the more
> generic function dma_request_slave_channel().
>
> Signed-off-by: Signed-off-by: Daniel Mack <daniel@zonque.org>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
> drivers/mtd/nand/raw/marvell_nand.c | 17 +----------------
> 1 file changed, 1 insertion(+), 16 deletions(-)
>
Acked-by: Miquel Raynal <miquel.raynal@bootlin.com>
Thanks,
Miqu?l
^ permalink raw reply
* v4.17-rc1: regressions on N900, N950
From: Pavel Machek @ 2018-05-24 9:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180523220456.GY98604@atomide.com>
On Wed 2018-05-23 15:04:56, Tony Lindgren wrote:
> * Pavel Machek <pavel@ucw.cz> [180523 20:14]:
> > On Wed 2018-05-23 16:06:15, Pavel Machek wrote:
> > > On Wed 2018-05-23 00:56:38, Aaro Koskinen wrote:
> > > > Hi,
> > > >
> > > > On Tue, May 22, 2018 at 10:58:26PM +0200, Pavel Machek wrote:
> > > > > On Tue 2018-05-22 22:41:39, Aaro Koskinen wrote:
> > > > > > My device worked with v4.17-rc1 (haven't found time to test newer kernels),
> > > > > > but if you say the probe order is random then we must find some proper way
> > > > > > to express the dependency.
> > > > >
> > > > > I started bisect, but.. that will probably not be useful.
> > > > >
> > > > > If your device works ok in v4.17-rc1, it probably works in newer -rcs,
> > > > > too.
> > > >
> > > > Actually, my statement may be bogus... Now I tried again with -rc1
> > > > (and also -rc6) and it fails... But v4.16 works.
> > > >
> > > > > Thanks for the ordering hint, I'll try to figure out what is going on
> > > > > there.
> > > >
> > > > My bisection pointed to 6fa7324ac5489ad43c4b6351355b869bc5458bef which
> > > > doesn't seem to make any sense...?! So maybe there really is something
> > > > random stuff going on? :-(
> > >
> > > So... I did some experiments on v4.16.
> > >
> > > Swapping tsc2005 at 0 and lcd: acx565akm at 2 entries in the dts does break
> > > stuff.
> > >
> > > I thought it might be due to vio regulator, but it does not appear
> > > so... screen still works with tsc2005 driver disabled in .config. (so
> > > there's noone to enable vio regulator).
> >
> > Deleting tsc2005 at 0 entry also breaks screen.
> >
> > Replacing tsc2005 at 0 entry with
> >
> > foobar at 0 {
> > compatible = "not really with anything";
> > spi-max-frequency = <6000000>;
> > reg = <0>;
> > };
> >
> > still results in working touchscreen, removing any of the three fields
> > breaks it again.
>
> I bisected one regression down, see "omapdrm regression in v4.17-rc series"
> not sure if it covers all the issues being discussed here though.
This is something else... Video was very sensitive basically to random
stuff, even in v4.16, and I tried to debug that. If I remove dts
support for touchscreen, video stops working -- and that's bad.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180524/14759d18/attachment.sig>
^ permalink raw reply
* [PATCH v10 09/18] KVM: arm64: Repurpose vcpu_arch.debug_flags for general-purpose flags
From: Alex Bennée @ 2018-05-24 9:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527005119-6842-10-git-send-email-Dave.Martin@arm.com>
Dave Martin <Dave.Martin@arm.com> writes:
> In struct vcpu_arch, the debug_flags field is used to store
> debug-related flags about the vcpu state.
>
> Since we are about to add some more flags related to FPSIMD and
> SVE, it makes sense to add them to the existing flags field rather
> than adding new fields. Since there is only one debug_flags flag
> defined so far, there is plenty of free space for expansion.
>
> In preparation for adding more flags, this patch renames the
> debug_flags field to simply "flags", and updates comments
> appropriately.
>
> The flag definitions are also moved to <asm/kvm_host.h>, since
> their presence in <asm/kvm_asm.h> was for purely historical
> reasons: these definitions are not used from asm any more, and not
> very likely to be as more Hyp asm is migrated to C.
>
> KVM_ARM64_DEBUG_DIRTY_SHIFT has not been used since commit
> 1ea66d27e7b0 ("arm64: KVM: Move away from the assembly version of
> the world switch"), so this patch gets rid of that too.
>
> No functional change.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
> Acked-by: Christoffer Dall <christoffer.dall@arm.com>
Reviewed-by: Alex Benn?e <alex.bennee@linaro.org>
> ---
> arch/arm64/include/asm/kvm_asm.h | 3 ---
> arch/arm64/include/asm/kvm_host.h | 7 +++++--
> arch/arm64/kvm/debug.c | 8 ++++----
> arch/arm64/kvm/hyp/debug-sr.c | 6 +++---
> arch/arm64/kvm/hyp/sysreg-sr.c | 4 ++--
> arch/arm64/kvm/sys_regs.c | 9 ++++-----
> 6 files changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index f6648a3..f62ccbf 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -30,9 +30,6 @@
> /* The hyp-stub will return this for any kvm_call_hyp() call */
> #define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR
>
> -#define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
> -#define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
> -
> /* Translate a kernel address of @sym into its equivalent linear mapping */
> #define kvm_ksym_ref(sym) \
> ({ \
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 469de8a..146c167 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -216,8 +216,8 @@ struct kvm_vcpu_arch {
> /* Exception Information */
> struct kvm_vcpu_fault_info fault;
>
> - /* Guest debug state */
> - u64 debug_flags;
> + /* Miscellaneous vcpu state flags */
> + u64 flags;
>
> /*
> * We maintain more than a single set of debug registers to support
> @@ -293,6 +293,9 @@ struct kvm_vcpu_arch {
> bool sysregs_loaded_on_cpu;
> };
>
> +/* vcpu_arch flags field values: */
> +#define KVM_ARM64_DEBUG_DIRTY (1 << 0)
> +
> #define vcpu_gp_regs(v) (&(v)->arch.ctxt.gp_regs)
>
> /*
> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
> index a1f4ebd..00d4223 100644
> --- a/arch/arm64/kvm/debug.c
> +++ b/arch/arm64/kvm/debug.c
> @@ -103,7 +103,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
> *
> * Additionally, KVM only traps guest accesses to the debug registers if
> * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY
> - * flag on vcpu->arch.debug_flags). Since the guest must not interfere
> + * flag on vcpu->arch.flags). Since the guest must not interfere
> * with the hardware state when debugging the guest, we must ensure that
> * trapping is enabled whenever we are debugging the guest using the
> * debug registers.
> @@ -111,7 +111,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
>
> void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
> {
> - bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
> + bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY);
> unsigned long mdscr;
>
> trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
> @@ -184,7 +184,7 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
> vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
>
> vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
> - vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
> trap_debug = true;
>
> trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
> @@ -206,7 +206,7 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
>
> /* If KDE or MDE are set, perform a full save/restore cycle. */
> if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE))
> - vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
>
> trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
> trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1));
> diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c
> index 3e717f6..5000976 100644
> --- a/arch/arm64/kvm/hyp/debug-sr.c
> +++ b/arch/arm64/kvm/hyp/debug-sr.c
> @@ -163,7 +163,7 @@ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
> if (!has_vhe())
> __debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
>
> - if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
> + if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
> return;
>
> host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
> @@ -185,7 +185,7 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
> if (!has_vhe())
> __debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
>
> - if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
> + if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
> return;
>
> host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
> @@ -196,7 +196,7 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
> __debug_save_state(vcpu, guest_dbg, guest_ctxt);
> __debug_restore_state(vcpu, host_dbg, host_ctxt);
>
> - vcpu->arch.debug_flags &= ~KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags &= ~KVM_ARM64_DEBUG_DIRTY;
> }
>
> u32 __hyp_text __kvm_get_mdcr_el2(void)
> diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
> index b3894df..35bc168 100644
> --- a/arch/arm64/kvm/hyp/sysreg-sr.c
> +++ b/arch/arm64/kvm/hyp/sysreg-sr.c
> @@ -196,7 +196,7 @@ void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
> sysreg[DACR32_EL2] = read_sysreg(dacr32_el2);
> sysreg[IFSR32_EL2] = read_sysreg(ifsr32_el2);
>
> - if (has_vhe() || vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
> + if (has_vhe() || vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)
> sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2);
> }
>
> @@ -218,7 +218,7 @@ void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu)
> write_sysreg(sysreg[DACR32_EL2], dacr32_el2);
> write_sysreg(sysreg[IFSR32_EL2], ifsr32_el2);
>
> - if (has_vhe() || vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
> + if (has_vhe() || vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)
> write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2);
> }
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 6e3b969..a436373 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -31,7 +31,6 @@
> #include <asm/debug-monitors.h>
> #include <asm/esr.h>
> #include <asm/kvm_arm.h>
> -#include <asm/kvm_asm.h>
> #include <asm/kvm_coproc.h>
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_host.h>
> @@ -338,7 +337,7 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
> {
> if (p->is_write) {
> vcpu_write_sys_reg(vcpu, p->regval, r->reg);
> - vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
> } else {
> p->regval = vcpu_read_sys_reg(vcpu, r->reg);
> }
> @@ -369,7 +368,7 @@ static void reg_to_dbg(struct kvm_vcpu *vcpu,
> }
>
> *dbg_reg = val;
> - vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
> }
>
> static void dbg_to_reg(struct kvm_vcpu *vcpu,
> @@ -1441,7 +1440,7 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
> {
> if (p->is_write) {
> vcpu_cp14(vcpu, r->reg) = p->regval;
> - vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
> } else {
> p->regval = vcpu_cp14(vcpu, r->reg);
> }
> @@ -1473,7 +1472,7 @@ static bool trap_xvr(struct kvm_vcpu *vcpu,
> val |= p->regval << 32;
> *dbg_reg = val;
>
> - vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
> + vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
> } else {
> p->regval = *dbg_reg >> 32;
> }
--
Alex Benn?e
^ permalink raw reply
* [PATCH v10 07/18] arm64: fpsimd: Eliminate task->mm checks
From: Alex Bennée @ 2018-05-24 9:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527005119-6842-8-git-send-email-Dave.Martin@arm.com>
Dave Martin <Dave.Martin@arm.com> writes:
> Currently the FPSIMD handling code uses the condition task->mm ==
> NULL as a hint that task has no FPSIMD register context.
>
> The ->mm check is only there to filter out tasks that cannot
> possibly have FPSIMD context loaded, for optimisation purposes.
> Also, TIF_FOREIGN_FPSTATE must always be checked anyway before
> saving FPSIMD context back to memory. For these reasons, the ->mm
> checks are not useful, providing that that TIF_FOREIGN_FPSTATE is
> maintained in a consistent way for kernel threads.
>
> This is true by construction however: TIF_FOREIGN_FPSTATE is never
> cleared except when returning to userspace or returning from a
> signal: thus, for a true kernel thread no FPSIMD context is ever
> loaded, TIF_FOREIGN_FPSTATE will remain set and no context will
> ever be saved.
>
> This patch removes the redundant checks and special-case code.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
With Christoffer's commit text:
Reviewed-by: Alex Benn?e <alex.bennee@linaro.org>
>
> ---
>
> Changes since v9:
>
> * New patch. Introduced during debugging, since the ->mm checks
> appear bogus and/or redundant, so are likely to be hiding or
> causing bugs.
> ---
> arch/arm64/include/asm/thread_info.h | 1 +
> arch/arm64/kernel/fpsimd.c | 38 ++++++++++++------------------------
> 2 files changed, 14 insertions(+), 25 deletions(-)
>
> diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
> index 740aa03c..a2ac914 100644
> --- a/arch/arm64/include/asm/thread_info.h
> +++ b/arch/arm64/include/asm/thread_info.h
> @@ -47,6 +47,7 @@ struct thread_info {
>
> #define INIT_THREAD_INFO(tsk) \
> { \
> + .flags = _TIF_FOREIGN_FPSTATE, \
> .preempt_count = INIT_PREEMPT_COUNT, \
> .addr_limit = KERNEL_DS, \
> }
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 3aa100a..1222491 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -891,31 +891,21 @@ asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
>
> void fpsimd_thread_switch(struct task_struct *next)
> {
> + bool wrong_task, wrong_cpu;
> +
> if (!system_supports_fpsimd())
> return;
> - /*
> - * Save the current FPSIMD state to memory, but only if whatever is in
> - * the registers is in fact the most recent userland FPSIMD state of
> - * 'current'.
> - */
> - if (current->mm)
> - fpsimd_save();
>
> - if (next->mm) {
> - /*
> - * If we are switching to a task whose most recent userland
> - * FPSIMD state is already in the registers of *this* cpu,
> - * we can skip loading the state from memory. Otherwise, set
> - * the TIF_FOREIGN_FPSTATE flag so the state will be loaded
> - * upon the next return to userland.
> - */
> - bool wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
> + /* Save unsaved fpsimd state, if any: */
> + fpsimd_save();
> +
> + /* Fix up TIF_FOREIGN_FPSTATE to correctly describe next's state: */
> + wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
> &next->thread.uw.fpsimd_state;
> - bool wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
> + wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
>
> - update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
> - wrong_task || wrong_cpu);
> - }
> + update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
> + wrong_task || wrong_cpu);
> }
>
> void fpsimd_flush_thread(void)
> @@ -1120,9 +1110,8 @@ void kernel_neon_begin(void)
>
> __this_cpu_write(kernel_neon_busy, true);
>
> - /* Save unsaved task fpsimd state, if any: */
> - if (current->mm)
> - fpsimd_save();
> + /* Save unsaved fpsimd state, if any: */
> + fpsimd_save();
>
> /* Invalidate any task state remaining in the fpsimd regs: */
> fpsimd_flush_cpu_state();
> @@ -1244,8 +1233,7 @@ static int fpsimd_cpu_pm_notifier(struct notifier_block *self,
> {
> switch (cmd) {
> case CPU_PM_ENTER:
> - if (current->mm)
> - fpsimd_save();
> + fpsimd_save();
> fpsimd_flush_cpu_state();
> break;
> case CPU_PM_EXIT:
--
Alex Benn?e
^ permalink raw reply
* Patch "staging: bcm2835-audio: Release resources on module_exit()" has been added to the 4.14-stable tree
From: gregkh at linuxfoundation.org @ 2018-05-24 9:18 UTC (permalink / raw)
To: linux-arm-kernel
This is a note to let you know that I've just added the patch titled
staging: bcm2835-audio: Release resources on module_exit()
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
staging-bcm2835-audio-release-resources-on-module_exit.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.
>From foo at baz Thu May 24 11:09:34 CEST 2018
From: Kirill Marinushkin <k.marinushkin@gmail.com>
Date: Fri, 23 Mar 2018 20:32:54 +0100
Subject: staging: bcm2835-audio: Release resources on module_exit()
From: Kirill Marinushkin <k.marinushkin@gmail.com>
[ Upstream commit 626118b472d2eb45f83a0276a18d3e6a01c69f6a ]
In the current implementation, `rmmod snd_bcm2835` does not release
resources properly. It causes an oops when trying to list sound devices.
This commit fixes it.
The details WRT allocation / free are described below.
Device structure WRT allocation:
pdev
\childdev[]
\card
\chip
\pcm
\ctl
Allocation / register sequence:
* childdev: devm_kzalloc - freed during driver detach
* childdev: device_initialize - freed during device_unregister
* pdev: devres_alloc - freed during driver detach
* childdev: device_add - removed during device_unregister
* pdev, childdev: devres_add - freed during driver detach
* card: snd_card_new - freed during snd_card_free
* chip: kzalloc - freed during kfree
* card, chip: snd_device_new - freed during snd_device_free
* chip: new_pcm - TODO: free pcm
* chip: new_ctl - TODO: free ctl
* card: snd_card_register - unregistered during snd_card_free
Free / unregister sequence:
* card: snd_card_free
* card, chip: snd_device_free
* childdev: device_unregister
* chip: kfree
Steps to reproduce the issue before this commit:
~~~~
$ rmmod snd_bcm2835
$ aplay -L
[ 138.648130] Unable to handle kernel paging request at virtual address 7f1343c0
[ 138.660415] pgd = ad8f0000
[ 138.665567] [7f1343c0] *pgd=3864c811, *pte=00000000, *ppte=00000000
[ 138.674887] Internal error: Oops: 7 [#1] SMP ARM
[ 138.683571] Modules linked in: sha256_generic cfg80211 rfkill snd_pcm snd_timer
snd fixed uio_pdrv_genirq uio ip_tables x_tables ipv6 [last unloaded: snd_bcm2835
]
[ 138.706594] CPU: 3 PID: 463 Comm: aplay Tainted: G WC 4.15.0-rc1-v
7+ #6
[ 138.719833] Hardware name: BCM2835
[ 138.726016] task: b877ac00 task.stack: aebec000
[ 138.733408] PC is at try_module_get+0x38/0x24c
[ 138.740813] LR is at snd_ctl_open+0x58/0x194 [snd]
[ 138.748485] pc : [<801c4d5c>] lr : [<7f0e6b2c>] psr: 20000013
[ 138.757709] sp : aebedd60 ip : aebedd88 fp : aebedd84
[ 138.765884] r10: 00000000 r9 : 00000004 r8 : 7f0ed440
[ 138.774040] r7 : b7e469b0 r6 : 7f0e6b2c r5 : afd91900 r4 : 7f1343c0
[ 138.783571] r3 : aebec000 r2 : 00000001 r1 : b877ac00 r0 : 7f1343c0
[ 138.793084] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
[ 138.803300] Control: 10c5387d Table: 2d8f006a DAC: 00000055
[ 138.812064] Process aplay (pid: 463, stack limit = 0xaebec210)
[ 138.820868] Stack: (0xaebedd60 to 0xaebee000)
[ 138.828207] dd60: 00000000 b848d000 afd91900 00000000 b7e469b0 7f0ed440 aebedda4 aebedd88
[ 138.842371] dd80: 7f0e6b2c 801c4d30 afd91900 7f0ea4dc 00000000 b7e469b0 aebeddcc aebedda8
[ 138.856611] dda0: 7f0e250c 7f0e6ae0 7f0e2464 b8478ec0 b7e469b0 afd91900 7f0ea388 00000000
[ 138.870864] ddc0: aebeddf4 aebeddd0 802ce590 7f0e2470 8090ab64 afd91900 afd91900 b7e469b0
[ 138.885301] dde0: afd91908 802ce4e4 aebede1c aebeddf8 802c57b4 802ce4f0 afd91900 aebedea8
[ 138.900110] de00: b7fa4c00 00000000 00000000 00000004 aebede3c aebede20 802c6ba8 802c56b4
[ 138.915260] de20: aebedea8 00000000 aebedf5c 00000000 aebedea4 aebede40 802d9a68 802c6b58
[ 138.930661] de40: b874ddd0 00000000 00000000 00000001 00000041 00000000 afd91900 aebede70
[ 138.946402] de60: 00000000 00000000 00000002 b7e469b0 b8a87610 b8d6ab80 801852f8 00080000
[ 138.962314] de80: aebedf5c aebedea8 00000001 80108464 aebec000 00000000 aebedf4c aebedea8
[ 138.978414] dea0: 802dacd4 802d970c b8a87610 b8d6ab80 a7982bc6 00000009 af363019 b9231480
[ 138.994617] dec0: 00000000 b8c038a0 b7e469b0 00000101 00000002 00000238 00000000 00000000
[ 139.010823] dee0: 00000000 aebedee8 00080000 0000000f aebedf3c aebedf00 802ed7e4 80843f94
[ 139.027025] df00: 00000003 00080000 b9231490 b9231480 00000000 00080000 af363000 00000000
[ 139.043229] df20: 00000005 00000002 ffffff9c 00000000 00080000 ffffff9c af363000 00000003
[ 139.059430] df40: aebedf94 aebedf50 802c6f70 802dac70 aebec000 00000000 00000001 00000000
[ 139.075629] df60: 00020000 00000004 00000100 00000001 7ebe577c 0002e038 00000000 00000005
[ 139.091828] df80: 80108464 aebec000 aebedfa4 aebedf98 802c7060 802c6e6c 00000000 aebedfa8
[ 139.108025] dfa0: 801082c0 802c7040 7ebe577c 0002e038 7ebe577c 00080000 00000b98 e81c8400
[ 139.124222] dfc0: 7ebe577c 0002e038 00000000 00000005 7ebe57e4 00a20af8 7ebe57f0 76f87394
[ 139.140419] dfe0: 00000000 7ebe55c4 76ec88e8 76df1d9c 60000010 7ebe577c 00000000 00000000
[ 139.156715] [<801c4d5c>] (try_module_get) from [<7f0e6b2c>] (snd_ctl_open+0x58/0x194 [snd])
[ 139.173222] [<7f0e6b2c>] (snd_ctl_open [snd]) from [<7f0e250c>] (snd_open+0xa8/0x14c [snd])
[ 139.189683] [<7f0e250c>] (snd_open [snd]) from [<802ce590>] (chrdev_open+0xac/0x188)
[ 139.205465] [<802ce590>] (chrdev_open) from [<802c57b4>] (do_dentry_open+0x10c/0x314)
[ 139.221347] [<802c57b4>] (do_dentry_open) from [<802c6ba8>] (vfs_open+0x5c/0x88)
[ 139.236788] [<802c6ba8>] (vfs_open) from [<802d9a68>] (path_openat+0x368/0x944)
[ 139.248270] [<802d9a68>] (path_openat) from [<802dacd4>] (do_filp_open+0x70/0xc4)
[ 139.263731] [<802dacd4>] (do_filp_open) from [<802c6f70>] (do_sys_open+0x110/0x1d4)
[ 139.279378] [<802c6f70>] (do_sys_open) from [<802c7060>] (SyS_open+0x2c/0x30)
[ 139.290647] [<802c7060>] (SyS_open) from [<801082c0>] (ret_fast_syscall+0x0/0x28)
[ 139.306021] Code: e3c3303f e5932004 e2822001 e5832004 (e5943000)
[ 139.316265] ---[ end trace 7f3f7f6193b663ed ]---
[ 139.324956] note: aplay[463] exited with preempt_count 1
~~~~
Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Ray Jui <rjui@broadcom.com>
Cc: Scott Branden <sbranden@broadcom.com>
Cc: bcm-kernel-feedback-list at broadcom.com
Cc: Michael Zoran <mzoran@crowfest.net>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: linux-rpi-kernel at lists.infradead.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: devel at driverdev.osuosl.org
Cc: linux-kernel at vger.kernel.org
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/vc04_services/bcm2835-audio/bcm2835.c | 54 ++++++++----------
1 file changed, 25 insertions(+), 29 deletions(-)
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c
@@ -36,6 +36,10 @@ MODULE_PARM_DESC(enable_compat_alsa,
static void snd_devm_unregister_child(struct device *dev, void *res)
{
struct device *childdev = *(struct device **)res;
+ struct bcm2835_chip *chip = dev_get_drvdata(childdev);
+ struct snd_card *card = chip->card;
+
+ snd_card_free(card);
device_unregister(childdev);
}
@@ -61,6 +65,13 @@ static int snd_devm_add_child(struct dev
return 0;
}
+static void snd_bcm2835_release(struct device *dev)
+{
+ struct bcm2835_chip *chip = dev_get_drvdata(dev);
+
+ kfree(chip);
+}
+
static struct device *
snd_create_device(struct device *parent,
struct device_driver *driver,
@@ -76,6 +87,7 @@ snd_create_device(struct device *parent,
device_initialize(device);
device->parent = parent;
device->driver = driver;
+ device->release = snd_bcm2835_release;
dev_set_name(device, "%s", name);
@@ -86,18 +98,19 @@ snd_create_device(struct device *parent,
return device;
}
-static int snd_bcm2835_free(struct bcm2835_chip *chip)
-{
- kfree(chip);
- return 0;
-}
-
/* component-destructor
* (see "Management of Cards and Components")
*/
static int snd_bcm2835_dev_free(struct snd_device *device)
{
- return snd_bcm2835_free(device->device_data);
+ struct bcm2835_chip *chip = device->device_data;
+ struct snd_card *card = chip->card;
+
+ /* TODO: free pcm, ctl */
+
+ snd_device_free(card, chip);
+
+ return 0;
}
/* chip-specific constructor
@@ -122,7 +135,7 @@ static int snd_bcm2835_create(struct snd
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err) {
- snd_bcm2835_free(chip);
+ kfree(chip);
return err;
}
@@ -130,31 +143,14 @@ static int snd_bcm2835_create(struct snd
return 0;
}
-static void snd_devm_card_free(struct device *dev, void *res)
+static struct snd_card *snd_bcm2835_card_new(struct device *dev)
{
- struct snd_card *snd_card = *(struct snd_card **)res;
-
- snd_card_free(snd_card);
-}
-
-static struct snd_card *snd_devm_card_new(struct device *dev)
-{
- struct snd_card **dr;
struct snd_card *card;
int ret;
- dr = devres_alloc(snd_devm_card_free, sizeof(*dr), GFP_KERNEL);
- if (!dr)
- return ERR_PTR(-ENOMEM);
-
ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
- if (ret) {
- devres_free(dr);
+ if (ret)
return ERR_PTR(ret);
- }
-
- *dr = card;
- devres_add(dev, dr);
return card;
}
@@ -271,7 +267,7 @@ static int snd_add_child_device(struct d
return PTR_ERR(child);
}
- card = snd_devm_card_new(child);
+ card = snd_bcm2835_card_new(child);
if (IS_ERR(card)) {
dev_err(child, "Failed to create card");
return PTR_ERR(card);
@@ -313,7 +309,7 @@ static int snd_add_child_device(struct d
return err;
}
- dev_set_drvdata(child, card);
+ dev_set_drvdata(child, chip);
dev_info(child, "card created with %d channels\n", numchans);
return 0;
Patches currently in stable-queue which might be from k.marinushkin at gmail.com are
queue-4.14/staging-bcm2835-audio-release-resources-on-module_exit.patch
^ permalink raw reply
* [PATCH v10 04/18] KVM: arm/arm64: Introduce kvm_arch_vcpu_run_pid_change
From: Alex Bennée @ 2018-05-24 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524081110.GI55598@C02W217FHV2R.local>
Christoffer Dall <christoffer.dall@arm.com> writes:
> On Wed, May 23, 2018 at 03:40:26PM +0100, Dave Martin wrote:
>> On Wed, May 23, 2018 at 03:34:20PM +0100, Alex Benn?e wrote:
>> >
>> > Dave Martin <Dave.Martin@arm.com> writes:
>> >
>> > > From: Christoffer Dall <christoffer.dall@linaro.org>
>> > >
>> > > KVM/ARM differs from other architectures in having to maintain an
>> > > additional virtual address space from that of the host and the
>> > > guest, because we split the execution of KVM across both EL1 and
>> > > EL2.
>> > >
>> > > This results in a need to explicitly map data structures into EL2
>> > > (hyp) which are accessed from the hyp code. As we are about to be
>> > > more clever with our FPSIMD handling on arm64, which stores data in
>> > > the task struct and uses thread_info flags, we will have to map
>> > > parts of the currently executing task struct into the EL2 virtual
>> > > address space.
>> > >
>> > > However, we don't want to do this on every KVM_RUN, because it is a
>> > > fairly expensive operation to walk the page tables, and the common
>> > > execution mode is to map a single thread to a VCPU. By introducing
>> > > a hook that architectures can select with
>> > > HAVE_KVM_VCPU_RUN_PID_CHANGE, we do not introduce overhead for
>> > > other architectures, but have a simple way to only map the data we
>> > > need when required for arm64.
>> > >
>> > > This patch introduces the framework only, and wires it up in the
>> > > arm/arm64 KVM common code.
>> > >
>> > > No functional change.
>> > >
>> > > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
>> > > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>> > > Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
>> > > ---
>> > > include/linux/kvm_host.h | 9 +++++++++
>> > > virt/kvm/Kconfig | 3 +++
>> > > virt/kvm/kvm_main.c | 7 ++++++-
>> > > 3 files changed, 18 insertions(+), 1 deletion(-)
>> > >
>> > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
>> > > index 6930c63..4268ace 100644
>> > > --- a/include/linux/kvm_host.h
>> > > +++ b/include/linux/kvm_host.h
>> > > @@ -1276,4 +1276,13 @@ static inline long kvm_arch_vcpu_async_ioctl(struct file *filp,
>> > > void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
>> > > unsigned long start, unsigned long end);
>> > >
>> > > +#ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE
>> > > +int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);
>> > > +#else
>> > > +static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
>> > > +{
>> > > + return 0;
>> > > +}
>> > > +#endif /* CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE */
>> > > +
>> > > #endif
>> > > diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
>> > > index cca7e06..72143cf 100644
>> > > --- a/virt/kvm/Kconfig
>> > > +++ b/virt/kvm/Kconfig
>> > > @@ -54,3 +54,6 @@ config HAVE_KVM_IRQ_BYPASS
>> > >
>> > > config HAVE_KVM_VCPU_ASYNC_IOCTL
>> > > bool
>> > > +
>> > > +config HAVE_KVM_VCPU_RUN_PID_CHANGE
>> > > + bool
>> >
>> > This almost threw me as I thought you might be able to enable this and
>> > break the build, but apparently not:
>> >
>> > Reviewed-by: Alex Benn?e <alex.bennee@linaro.org>
>>
>> Without a "help", the option seems non-interactive and cannot be true
>> unless something selects it. It seems a bit weird to me too, but the
>> idiom appears widely used...
>>
> Indeed, I've copied this idiom from other things before and nobody has
> complained, so I think it works (without any further deep insights into
> the inner workings of Kconfig).
It's fine. My main worry was breaking bisection with the normal "make
olddefconfig" approach. I tested it and found it to be fine and I don't
think we need to worry about people adding the symbol to .config
manually - they get to keep both pieces ;-)
--
Alex Benn?e
^ permalink raw reply
* [PATCH v10 07/18] arm64: fpsimd: Eliminate task->mm checks
From: Alex Bennée @ 2018-05-24 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524083350.GK55598@C02W217FHV2R.local>
Christoffer Dall <christoffer.dall@arm.com> writes:
> On Wed, May 23, 2018 at 04:03:37PM +0100, Dave Martin wrote:
>> On Wed, May 23, 2018 at 03:56:57PM +0100, Catalin Marinas wrote:
>> > On Wed, May 23, 2018 at 02:31:59PM +0100, Dave P Martin wrote:
>> > > On Wed, May 23, 2018 at 01:48:12PM +0200, Christoffer Dall wrote:
>> > > > On Tue, May 22, 2018 at 05:05:08PM +0100, Dave Martin wrote:
>> > > > > This is true by construction however: TIF_FOREIGN_FPSTATE is never
>> > > > > cleared except when returning to userspace or returning from a
>> > > > > signal: thus, for a true kernel thread no FPSIMD context is ever
>> > > > > loaded, TIF_FOREIGN_FPSTATE will remain set and no context will
>> > > > > ever be saved.
>> > > >
>> > > > I don't understand this construction proof; from looking at the patch
>> > > > below it is not obvious to me why fpsimd_thread_switch() can never have
>> > > > !wrong_task && !wrong_cpu and therefore clear TIF_FOREIGN_FPSTATE for a
>> > > > kernel thread?
>> > >
>> > > Looking at this again, I think it is poorly worded. This patch aims to
>> > > make it true by construction, but it isn't prior to the patch.
>> > >
>> > > I'm tempted to delete the paragraph: the assertion of both untrue and
>> > > not the best way to justify that this patch works.
>> > >
>> > >
>> > > How about:
>> > >
>> > > -8<-
>> > >
>> > > The context switch logic already isolates user threads from each other.
>> > > This, it is sufficient for isolating user threads from the kernel,
>
> s/This/Thus/ ?
>
> I don't understand what 'it' refers to here?
>
>> > > since the goal either way is to ensure that code executing in userspace
>> > > cannot see any FPSIMD state except its own. Thus, there is no special
>> > > property of kernel threads that we care about except that it is
>> > > pointless to save or load FPSIMD register state for them.
>
> Actually, I'm not really sure what this paragraph is getting at.
>
>> > >
>> > > At worst, the removal of all the kernel thread special cases by this
>> > > patch would thus spuriously load and save state for kernel threads when
>> > > unnecessary.
>> > >
>> > > But the context switch logic is already deliberately optimised to defer
>> > > reloads of the regs until ret_to_user (or sigreturn as a special case),
>> > > which kernel threads by definition never reach.
>> > >
>> > > ->8-
>> >
>> > The "at worst" paragraph makes it look like it could happen (at least
>> > until you reach the last paragraph). Maybe you can just say that
>> > wrong_task and wrong_cpu (with the fpsimd_cpu = NR_CPUS addition) are
>> > always true for kernel threads. You should probably mention this in a
>> > comment in the code as well.
>>
>> What if I just delete the second paragraph, and remove the "But" from
>> the start of the third, and append:
>>
>> "As a result, the wrong_task and wrong_cpu tests in
>> fpsimd_thread_switch() will always yield false for kernel threads."
>>
>> ...with a similar comment in the code?
>
> ...with a risk of being a bit over-pedantic and annoying, may I suggest
> the following complete commit text:
>
> ------8<------
> Currently the FPSIMD handling code uses the condition task->mm ==
> NULL as a hint that task has no FPSIMD register context.
>
> The ->mm check is only there to filter out tasks that cannot
> possibly have FPSIMD context loaded, for optimisation purposes.
> However, TIF_FOREIGN_FPSTATE must always be checked anyway before
> saving FPSIMD context back to memory. For this reason, the ->mm
> checks are not useful, providing that that TIF_FOREIGN_FPSTATE is
> maintained properly for kernel threads.
>
> FPSIMD context is never preserved for kernel threads across a context
> switch and therefore TIF_FOREIGN_FPSTATE should always be true for
> kernel threads. This is indeed the case, as the wrong_task and
> wrong_cpu tests in fpsimd_thread_switch() will always yield false for
> kernel threads.
>
> Further, the context switch logic is already deliberately optimised to
> defer reloads of the FPSIMD context until ret_to_user (or sigreturn as a
> special case), which kernel threads by definition never reach, and
> therefore this change introduces no additional work in the critical
> path.
>
> This patch removes the redundant checks and special-case code.
> ------8<------
FWIW I prefer this version for the commit text.
--
Alex Benn?e
^ permalink raw reply
* [PATCH v7 00/26] PM / Domains: Support hierarchical CPU arrangement (PSCI/ARM)
From: Ulf Hansson @ 2018-05-24 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1523531671-27491-1-git-send-email-ulf.hansson@linaro.org>
Sudeep, Lorenzo, Mark
On 12 April 2018 at 13:14, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> Changes in v7:
> - Addressed comments concerning the PSCI changes from Mark Rutland, which moves
> the psci firmware driver to a new firmware subdir and change to force PSCI PC
> mode during boot to cope with kexec'ed booted kernels.
Are you guys happy in general with the PSCI specific parts from this
series? It would be nice if you could provide me with acks or
reviewed-by tags for the rest of them in such case.
I intend to re-post a new version very soon.
[...]
Kind regards
Uffe
^ permalink raw reply
* [PATCH v10 05/18] KVM: arm64: Convert lazy FPSIMD context switch trap to C
From: Alex Bennée @ 2018-05-24 9:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180524085445.GP13470@e103592.cambridge.arm.com>
Dave Martin <Dave.Martin@arm.com> writes:
> On Thu, May 24, 2018 at 10:12:20AM +0200, Christoffer Dall wrote:
>> On Wed, May 23, 2018 at 08:35:13PM +0100, Alex Benn?e wrote:
>> >
>> > Dave Martin <Dave.Martin@arm.com> writes:
>> >
>> > > To make the lazy FPSIMD context switch trap code easier to hack on,
>> > > this patch converts it to C.
>> > >
>> > > This is not amazingly efficient, but the trap should typically only
>> > > be taken once per host context switch.
>> > >
>> > > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>> > > Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
>> > > ---
>> > > arch/arm64/kvm/hyp/entry.S | 57 +++++++++++++++++----------------------------
>> > > arch/arm64/kvm/hyp/switch.c | 24 +++++++++++++++++++
>> > > 2 files changed, 46 insertions(+), 35 deletions(-)
>
> [...]
>
>> > > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
>> > > index d964523..c0796c4 100644
>> > > --- a/arch/arm64/kvm/hyp/switch.c
>> > > +++ b/arch/arm64/kvm/hyp/switch.c
>> > > @@ -318,6 +318,30 @@ static bool __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
>> > > }
>> > > }
>> > >
>> > > +void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused,
>> > > + struct kvm_vcpu *vcpu)
>> > > +{
>> > > + kvm_cpu_context_t *host_ctxt;
>> > > +
>> > > + if (has_vhe())
>> > > + write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
>> > > + cpacr_el1);
>> > > + else
>> > > + write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP,
>> > > + cptr_el2);
>> >
>> > Is there no way to do alternative() in C or does it always come down to
>> > different inline asms?
>> >
>>
>> has_vhe() should resolve to a static key, and I prefer this over the
>> previous alternative construct we had for selecting function calls in C,
>> as that resultet in having to follow too many levels of indirection.
>
> I'll defer to Christoffer on that -- I was just following precedent :)
>
> The if (has_vhe()) approach has the benefit of being much more
> readable, and the static branch predictor in many CPUs will succeed in
> folding a short-range unconditional branch out entirely. There will be
> a small increase in I-cache pressure due to the larger inline code
> size, but probably not much beyond that.
Fair enough - it was mostly a curiosity. It seems most of the use of
alternative() are mostly at the low level instruction level anyway.
--
Alex Benn?e
^ permalink raw reply
* [PATCH v10 17/18] KVM: arm64: Fold redundant exit code checks out of fixup_guest_exit()
From: Christoffer Dall @ 2018-05-24 9:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527005119-6842-18-git-send-email-Dave.Martin@arm.com>
On Tue, May 22, 2018 at 05:05:18PM +0100, Dave Martin wrote:
> The entire tail of fixup_guest_exit() is contained in if statements
> of the form if (x && *exit_code == ARM_EXCEPTION_TRAP). As a result,
> we can check just once and bail out of the function early, allowing
> the remaining if conditions to be simplified.
>
> The only awkward case is where *exit_code is changed to
> ARM_EXCEPTION_EL1_SERROR in the case of an illegal GICv2 CPU
> interface access: in that case, the GICv3 trap handling code is
> skipped using a goto. This avoids pointlessly evaluating the
> static branch check for the GICv3 case, even though we can't have
> vgic_v2_cpuif_trap and vgic_v3_cpuif_trap true simultaneously
> unless we have a GICv3 and GICv2 on the host: that sounds stupid,
> but I haven't satisfied myself that it can't happen.
>
> No functional change.
Acked-by: Christoffer Dall <christoffer.dall@arm.com>
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm64/kvm/hyp/switch.c | 12 ++++++++----
> 1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 18d0faa..4fbee95 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -387,11 +387,13 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> * same PC once the SError has been injected, and replay the
> * trapping instruction.
> */
> - if (*exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
> + if (*exit_code != ARM_EXCEPTION_TRAP)
> + goto exit;
> +
> + if (!__populate_fault_info(vcpu))
> return true;
>
> - if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
> - *exit_code == ARM_EXCEPTION_TRAP) {
> + if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
> bool valid;
>
> valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW &&
> @@ -417,11 +419,12 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
> *exit_code = ARM_EXCEPTION_EL1_SERROR;
> }
> +
> + goto exit;
> }
> }
>
> if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
> - *exit_code == ARM_EXCEPTION_TRAP &&
> (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
> kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
> int ret = __vgic_v3_perform_cpuif_access(vcpu);
> @@ -430,6 +433,7 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> return true;
> }
>
> +exit:
> /* Return to the host kernel and handle the exit */
> return false;
> }
> --
> 2.1.4
>
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
^ permalink raw reply
* [PATCH v10 16/18] KVM: arm64: Remove redundant *exit_code changes in fpsimd_guest_exit()
From: Christoffer Dall @ 2018-05-24 9:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527005119-6842-17-git-send-email-Dave.Martin@arm.com>
On Tue, May 22, 2018 at 05:05:17PM +0100, Dave Martin wrote:
> In fixup_guest_exit(), there are a couple of cases where after
> checking what the exit code was, we assign it explicitly with the
> value it already had.
>
> Assuming this is not indicative of a bug, these assignments are not
> needed.
>
> This patch removes the redundant assignments, and simplifies some
> if-nesting that becomes trivial as a result.
>
> No functional change.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Christoffer Dall <christoffer.dall@arm.com>
> ---
> arch/arm64/kvm/hyp/switch.c | 16 ++++------------
> 1 file changed, 4 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index a6a8c7d..18d0faa 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -403,12 +403,8 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> if (valid) {
> int ret = __vgic_v2_perform_cpuif_access(vcpu);
>
> - if (ret == 1) {
> - if (__skip_instr(vcpu))
> - return true;
> - else
> - *exit_code = ARM_EXCEPTION_TRAP;
> - }
> + if (ret == 1 && __skip_instr(vcpu))
> + return true;
>
> if (ret == -1) {
> /* Promote an illegal access to an
> @@ -430,12 +426,8 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
> int ret = __vgic_v3_perform_cpuif_access(vcpu);
>
> - if (ret == 1) {
> - if (__skip_instr(vcpu))
> - return true;
> - else
> - *exit_code = ARM_EXCEPTION_TRAP;
> - }
> + if (ret == 1 && __skip_instr(vcpu))
> + return true;
> }
>
> /* Return to the host kernel and handle the exit */
> --
> 2.1.4
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v10 14/18] KVM: arm64: Save host SVE context as appropriate
From: Christoffer Dall @ 2018-05-24 9:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527005119-6842-15-git-send-email-Dave.Martin@arm.com>
On Tue, May 22, 2018 at 05:05:15PM +0100, Dave Martin wrote:
> This patch adds SVE context saving to the hyp FPSIMD context switch
> path. This means that it is no longer necessary to save the host
> SVE state in advance of entering the guest, when in use.
>
> In order to avoid adding pointless complexity to the code, VHE is
> assumed if SVE is in use. VHE is an architectural prerequisite for
> SVE, so there is no good reason to turn CONFIG_ARM64_VHE off in
> kernels that support both SVE and KVM.
>
> Historically, software models exist that can expose the
> architecturally invalid configuration of SVE without VHE, so if
> this situation is detected at kvm_init() time then KVM will be
> disabled.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>
> ---
>
> * Tags stripped since v8, please reconfirm if possible:
>
> Formerly-Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
> Formerly-Acked-by: Marc Zyngier <marc.zyngier@arm.com>
> Formerly-Acked-by: Catalin Marinas <catalin.marinas@arm.com>
>
> Changes since v9:
>
> Requested by Marc Zyngier:
>
> * Inline check for VHE if SVE is present into kvm_host.h.
>
> The check has been renamed to the more specific
> kvm_arch_check_sve_has_vhe(), and the kvm_pr_unimpl() moved back to
> arm.c (to avoid circular include issues).
>
> arm.c is not single-arch code, but it is all Arm-specific, so
> adding a hook like this doesn't seem too unreasonable.
>
> Changes since v8:
>
> * Add kvm_arch_check_supported() hook, and move arm64-specific check
> for SVE-implies-VHE into arch/arm64/.
>
> Due to circular header dependency problems, it is difficult to get
> the prototype for kvm_pr_*() functions in <asm/kvm_host.h>, so this
> patch puts arm64's kvm_arch_check_supported() hook out of line.
> This is not a hot function.
> ---
> arch/arm/include/asm/kvm_host.h | 1 +
> arch/arm64/Kconfig | 7 +++++++
> arch/arm64/include/asm/kvm_host.h | 13 +++++++++++++
> arch/arm64/kvm/fpsimd.c | 1 -
> arch/arm64/kvm/hyp/switch.c | 20 +++++++++++++++++++-
> virt/kvm/arm/arm.c | 7 +++++++
> 6 files changed, 47 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index ac870b2..3b85bbb 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -280,6 +280,7 @@ void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
>
> struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
>
> +static inline bool kvm_arch_check_sve_has_vhe(void) { return true; }
> static inline void kvm_arch_hardware_unsetup(void) {}
> static inline void kvm_arch_sync_events(struct kvm *kvm) {}
> static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index eb2cf49..b0d3820 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1130,6 +1130,7 @@ endmenu
> config ARM64_SVE
> bool "ARM Scalable Vector Extension support"
> default y
> + depends on !KVM || ARM64_VHE
> help
> The Scalable Vector Extension (SVE) is an extension to the AArch64
> execution state which complements and extends the SIMD functionality
> @@ -1155,6 +1156,12 @@ config ARM64_SVE
> booting the kernel. If unsure and you are not observing these
> symptoms, you should assume that it is safe to say Y.
>
> + CPUs that support SVE are architecturally required to support the
> + Virtualization Host Extensions (VHE), so the kernel makes no
> + provision for supporting SVE alongside KVM without VHE enabled.
> + Thus, you will need to enable CONFIG_ARM64_VHE if you want to support
> + KVM in the same kernel image.
> +
> config ARM64_MODULE_PLTS
> bool
> select HAVE_MOD_ARCH_SPECIFIC
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index b3fe730..06d5a61 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -405,6 +405,19 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
> kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
> }
>
> +static inline bool kvm_arch_check_sve_has_vhe(void)
> +{
> + /*
> + * The Arm architecture specifies that imlpementation of SVE
nit: implementation
> + * requires VHE also to be implemented. The KVM code for arm64
> + * relies on this when SVE is present:
> + */
> + if (system_supports_sve())
> + return has_vhe();
> + else
> + return true;
> +}
> +
> static inline void kvm_arch_hardware_unsetup(void) {}
> static inline void kvm_arch_sync_events(struct kvm *kvm) {}
> static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index 365933a..dc6ecfa 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -59,7 +59,6 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
> */
> void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
> {
> - BUG_ON(system_supports_sve());
> BUG_ON(!current->mm);
>
> vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | KVM_ARM64_HOST_SVE_IN_USE);
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 118f300..a6a8c7d 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -21,6 +21,7 @@
>
> #include <kvm/arm_psci.h>
>
> +#include <asm/cpufeature.h>
> #include <asm/kvm_asm.h>
> #include <asm/kvm_emulate.h>
> #include <asm/kvm_host.h>
> @@ -28,6 +29,7 @@
> #include <asm/kvm_mmu.h>
> #include <asm/fpsimd.h>
> #include <asm/debug-monitors.h>
> +#include <asm/processor.h>
> #include <asm/thread_info.h>
>
> /* Check whether the FP regs were dirtied while in the host-side run loop: */
> @@ -329,6 +331,8 @@ static bool __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
> void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused,
> struct kvm_vcpu *vcpu)
> {
> + struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> +
> if (has_vhe())
> write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> cpacr_el1);
> @@ -339,7 +343,21 @@ void __hyp_text __hyp_switch_fpsimd(u64 esr __always_unused,
> isb();
>
> if (vcpu->arch.flags & KVM_ARM64_FP_HOST) {
> - __fpsimd_save_state(vcpu->arch.host_fpsimd_state);
> + /*
> + * In the SVE case, VHE is assumed: it is enforced by
> + * Kconfig and kvm_arch_init().
> + */
> + if (system_supports_sve() &&
> + (vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE)) {
> + struct thread_struct *thread = container_of(
> + host_fpsimd,
> + struct thread_struct, uw.fpsimd_state);
> +
> + sve_save_state(sve_pffr(thread), &host_fpsimd->fpsr);
> + } else {
> + __fpsimd_save_state(host_fpsimd);
> + }
> +
> vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
> }
>
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index bee226c..ce7c6f3 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -16,6 +16,7 @@
> * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> */
>
> +#include <linux/bug.h>
> #include <linux/cpu_pm.h>
> #include <linux/errno.h>
> #include <linux/err.h>
> @@ -41,6 +42,7 @@
> #include <asm/mman.h>
> #include <asm/tlbflush.h>
> #include <asm/cacheflush.h>
> +#include <asm/cpufeature.h>
> #include <asm/virt.h>
> #include <asm/kvm_arm.h>
> #include <asm/kvm_asm.h>
> @@ -1574,6 +1576,11 @@ int kvm_arch_init(void *opaque)
> return -ENODEV;
> }
>
> + if (!kvm_arch_check_sve_has_vhe()) {
> + kvm_pr_unimpl("SVE system without VHE unsupported. Broken cpu?");
> + return -ENODEV;
> + }
> +
> for_each_online_cpu(cpu) {
> smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1);
> if (ret < 0) {
> --
> 2.1.4
>
>
Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
^ permalink raw reply
* [rjarzmik:work/dma_slave_map 5/13] drivers/mtd/nand/raw/marvell_nand.c:2628:52: sparse: incorrect type in argument 1 (different base types)
From: kbuild test robot @ 2018-05-24 9:07 UTC (permalink / raw)
To: linux-arm-kernel
tree: https://github.com/rjarzmik/linux work/dma_slave_map
head: d18138ed977685f67fb18efcb5b5ef7084e3f1ae
commit: 38686a4ca1306465bae33d821a1128288f68ec6b [5/13] mtd: rawnand: marvell: remove the dmaengine compat need
reproduce:
# apt-get install sparse
git checkout 38686a4ca1306465bae33d821a1128288f68ec6b
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
drivers/mtd/nand/raw/marvell_nand.c:752:32: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:861:25: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:861:25: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:907:25: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:907:25: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:1572:41: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2238:24: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2238:24: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2240:24: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2240:24: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2262:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2263:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2264:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2265:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2266:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2267:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2268:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2271:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2272:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2273:17: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2277:25: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2279:25: sparse: expression using sizeof(void)
drivers/mtd/nand/raw/marvell_nand.c:2282:25: sparse: expression using sizeof(void)
>> drivers/mtd/nand/raw/marvell_nand.c:2628:52: sparse: incorrect type in argument 1 (different base types) @@ expected struct device *dev @@ got sstruct device *dev @@
drivers/mtd/nand/raw/marvell_nand.c:2628:52: expected struct device *dev
drivers/mtd/nand/raw/marvell_nand.c:2628:52: got struct device **<noident>
drivers/mtd/nand/raw/marvell_nand.c: In function 'marvell_nfc_init_dma':
drivers/mtd/nand/raw/marvell_nand.c:2628:44: error: passing argument 1 of 'dma_request_slave_channel' from incompatible pointer type [-Werror=incompatible-pointer-types]
nfc->dma_chan = dma_request_slave_channel(&nfc->dev, "data");
^
In file included from drivers/mtd/nand/raw/marvell_nand.c:21:0:
include/linux/dmaengine.h:1315:18: note: expected 'struct device *' but argument is of type 'struct device **'
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
^~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
vim +2628 drivers/mtd/nand/raw/marvell_nand.c
2608
2609 static int marvell_nfc_init_dma(struct marvell_nfc *nfc)
2610 {
2611 struct platform_device *pdev = container_of(nfc->dev,
2612 struct platform_device,
2613 dev);
2614 struct dma_slave_config config = {};
2615 struct resource *r;
2616 int ret;
2617
2618 if (!IS_ENABLED(CONFIG_PXA_DMA)) {
2619 dev_warn(nfc->dev,
2620 "DMA not enabled in configuration\n");
2621 return -ENOTSUPP;
2622 }
2623
2624 ret = dma_set_mask_and_coherent(nfc->dev, DMA_BIT_MASK(32));
2625 if (ret)
2626 return ret;
2627
> 2628 nfc->dma_chan = dma_request_slave_channel(&nfc->dev, "data");
2629 if (!nfc->dma_chan) {
2630 dev_err(nfc->dev,
2631 "Unable to request data DMA channel\n");
2632 return -ENODEV;
2633 }
2634
2635 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2636 if (!r)
2637 return -ENXIO;
2638
2639 config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2640 config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
2641 config.src_addr = r->start + NDDB;
2642 config.dst_addr = r->start + NDDB;
2643 config.src_maxburst = 32;
2644 config.dst_maxburst = 32;
2645 ret = dmaengine_slave_config(nfc->dma_chan, &config);
2646 if (ret < 0) {
2647 dev_err(nfc->dev, "Failed to configure DMA channel\n");
2648 return ret;
2649 }
2650
2651 /*
2652 * DMA must act on length multiple of 32 and this length may be
2653 * bigger than the destination buffer. Use this buffer instead
2654 * for DMA transfers and then copy the desired amount of data to
2655 * the provided buffer.
2656 */
2657 nfc->dma_buf = kmalloc(MAX_CHUNK_SIZE, GFP_KERNEL | GFP_DMA);
2658 if (!nfc->dma_buf)
2659 return -ENOMEM;
2660
2661 nfc->use_dma = true;
2662
2663 return 0;
2664 }
2665
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox