* Re: [PATCH v2 1/3] powerpc/mm: Enable radix GTSE only if supported.
From: Aneesh Kumar K.V @ 2020-06-30 5:26 UTC (permalink / raw)
To: Bharata B Rao, linuxppc-dev; +Cc: npiggin, Bharata B Rao
In-Reply-To: <20200626131000.5207-2-bharata@linux.ibm.com>
Bharata B Rao <bharata@linux.ibm.com> writes:
> Make GTSE an MMU feature and enable it by default for radix.
> However for guest, conditionally enable it if hypervisor supports
> it via OV5 vector. Let prom_init ask for radix GTSE only if the
> support exists.
>
> Having GTSE as an MMU feature will make it easy to enable radix
> without GTSE. Currently radix assumes GTSE is enabled by default.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
> ---
> arch/powerpc/include/asm/mmu.h | 4 ++++
> arch/powerpc/kernel/dt_cpu_ftrs.c | 1 +
> arch/powerpc/kernel/prom_init.c | 13 ++++++++-----
> arch/powerpc/mm/init_64.c | 5 ++++-
> 4 files changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
> index f4ac25d4df05..884d51995934 100644
> --- a/arch/powerpc/include/asm/mmu.h
> +++ b/arch/powerpc/include/asm/mmu.h
> @@ -28,6 +28,9 @@
> * Individual features below.
> */
>
> +/* Guest Translation Shootdown Enable */
> +#define MMU_FTR_GTSE ASM_CONST(0x00001000)
> +
> /*
> * Support for 68 bit VA space. We added that from ISA 2.05
> */
> @@ -173,6 +176,7 @@ enum {
> #endif
> #ifdef CONFIG_PPC_RADIX_MMU
> MMU_FTR_TYPE_RADIX |
> + MMU_FTR_GTSE |
> #ifdef CONFIG_PPC_KUAP
> MMU_FTR_RADIX_KUAP |
> #endif /* CONFIG_PPC_KUAP */
> diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
> index a0edeb391e3e..ac650c233cd9 100644
> --- a/arch/powerpc/kernel/dt_cpu_ftrs.c
> +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
> @@ -336,6 +336,7 @@ static int __init feat_enable_mmu_radix(struct dt_cpu_feature *f)
> #ifdef CONFIG_PPC_RADIX_MMU
> cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX;
> cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;
> + cur_cpu_spec->mmu_features |= MMU_FTR_GTSE;
> cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
>
> return 1;
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index 90c604d00b7d..cbc605cfdec0 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -1336,12 +1336,15 @@ static void __init prom_check_platform_support(void)
> }
> }
>
> - if (supported.radix_mmu && supported.radix_gtse &&
> - IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
> - /* Radix preferred - but we require GTSE for now */
> - prom_debug("Asking for radix with GTSE\n");
> + if (supported.radix_mmu && IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
> + /* Radix preferred - Check if GTSE is also supported */
> + prom_debug("Asking for radix\n");
> ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
> - ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE);
> + if (supported.radix_gtse)
> + ibm_architecture_vec.vec5.radix_ext =
> + OV5_FEAT(OV5_RADIX_GTSE);
> + else
> + prom_debug("Radix GTSE isn't supported\n");
> } else if (supported.hash_mmu) {
> /* Default to hash mmu (if we can) */
> prom_debug("Asking for hash\n");
> diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
> index bc73abf0bc25..152aa0200cef 100644
> --- a/arch/powerpc/mm/init_64.c
> +++ b/arch/powerpc/mm/init_64.c
> @@ -407,12 +407,15 @@ static void __init early_check_vec5(void)
> if (!(vec5[OV5_INDX(OV5_RADIX_GTSE)] &
> OV5_FEAT(OV5_RADIX_GTSE))) {
> pr_warn("WARNING: Hypervisor doesn't support RADIX with GTSE\n");
> - }
> + cur_cpu_spec->mmu_features &= ~MMU_FTR_GTSE;
> + } else
> + cur_cpu_spec->mmu_features |= MMU_FTR_GTSE;
> /* Do radix anyway - the hypervisor said we had to */
> cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX;
> } else if (mmu_supported == OV5_FEAT(OV5_MMU_HASH)) {
> /* Hypervisor only supports hash - disable radix */
> cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
> + cur_cpu_spec->mmu_features &= ~MMU_FTR_GTSE;
> }
> }
>
> --
> 2.21.3
^ permalink raw reply
* Re: [PATCH v2 2/3] powerpc/pseries: H_REGISTER_PROC_TBL should ask for GTSE only if enabled
From: Aneesh Kumar K.V @ 2020-06-30 5:26 UTC (permalink / raw)
To: Bharata B Rao, linuxppc-dev; +Cc: npiggin, Bharata B Rao
In-Reply-To: <20200626131000.5207-3-bharata@linux.ibm.com>
Bharata B Rao <bharata@linux.ibm.com> writes:
> H_REGISTER_PROC_TBL asks for GTSE by default. GTSE flag bit should
> be set only when GTSE is supported.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
> ---
> arch/powerpc/platforms/pseries/lpar.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
> index fd26f3d21d7b..f82569a505f1 100644
> --- a/arch/powerpc/platforms/pseries/lpar.c
> +++ b/arch/powerpc/platforms/pseries/lpar.c
> @@ -1680,9 +1680,11 @@ static int pseries_lpar_register_process_table(unsigned long base,
>
> if (table_size)
> flags |= PROC_TABLE_NEW;
> - if (radix_enabled())
> - flags |= PROC_TABLE_RADIX | PROC_TABLE_GTSE;
> - else
> + if (radix_enabled()) {
> + flags |= PROC_TABLE_RADIX;
> + if (mmu_has_feature(MMU_FTR_GTSE))
> + flags |= PROC_TABLE_GTSE;
> + } else
> flags |= PROC_TABLE_HPT_SLB;
> for (;;) {
> rc = plpar_hcall_norets(H_REGISTER_PROC_TBL, flags, base,
> --
> 2.21.3
^ permalink raw reply
* Re: [PATCH v2 3/3] powerpc/mm/book3s64/radix: Off-load TLB invalidations to host when !GTSE
From: Aneesh Kumar K.V @ 2020-06-30 5:26 UTC (permalink / raw)
To: Bharata B Rao, linuxppc-dev; +Cc: npiggin, Bharata B Rao
In-Reply-To: <20200626131000.5207-4-bharata@linux.ibm.com>
Bharata B Rao <bharata@linux.ibm.com> writes:
> From: Nicholas Piggin <npiggin@gmail.com>
>
> When platform doesn't support GTSE, let TLB invalidation requests
> for radix guests be off-loaded to the host using H_RPT_INVALIDATE
> hcall.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
> [hcall wrapper, error path handling and renames]
> ---
> .../include/asm/book3s/64/tlbflush-radix.h | 15 ++++
> arch/powerpc/include/asm/hvcall.h | 34 +++++++-
> arch/powerpc/include/asm/plpar_wrappers.h | 50 +++++++++++
> arch/powerpc/mm/book3s64/radix_tlb.c | 82 +++++++++++++++++--
> 4 files changed, 173 insertions(+), 8 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
> index ca8db193ae38..e7cf50358411 100644
> --- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
> +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
> @@ -2,10 +2,25 @@
> #ifndef _ASM_POWERPC_TLBFLUSH_RADIX_H
> #define _ASM_POWERPC_TLBFLUSH_RADIX_H
>
> +#include <asm/hvcall.h>
> +
> struct vm_area_struct;
> struct mm_struct;
> struct mmu_gather;
>
> +static inline u64 psize_to_h_rpti(unsigned long psize)
> +{
> + if (psize == MMU_PAGE_4K)
> + return H_RPTI_PAGE_4K;
> + if (psize == MMU_PAGE_64K)
> + return H_RPTI_PAGE_64K;
> + if (psize == MMU_PAGE_2M)
> + return H_RPTI_PAGE_2M;
> + if (psize == MMU_PAGE_1G)
> + return H_RPTI_PAGE_1G;
> + return H_RPTI_PAGE_ALL;
> +}
> +
> static inline int mmu_get_ap(int psize)
> {
> return mmu_psize_defs[psize].ap;
> diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
> index e90c073e437e..43486e773bd6 100644
> --- a/arch/powerpc/include/asm/hvcall.h
> +++ b/arch/powerpc/include/asm/hvcall.h
> @@ -305,7 +305,8 @@
> #define H_SCM_UNBIND_ALL 0x3FC
> #define H_SCM_HEALTH 0x400
> #define H_SCM_PERFORMANCE_STATS 0x418
> -#define MAX_HCALL_OPCODE H_SCM_PERFORMANCE_STATS
> +#define H_RPT_INVALIDATE 0x448
> +#define MAX_HCALL_OPCODE H_RPT_INVALIDATE
>
> /* Scope args for H_SCM_UNBIND_ALL */
> #define H_UNBIND_SCOPE_ALL (0x1)
> @@ -389,6 +390,37 @@
> #define PROC_TABLE_RADIX 0x04
> #define PROC_TABLE_GTSE 0x01
>
> +/*
> + * Defines for
> + * H_RPT_INVALIDATE - Invalidate RPT translation lookaside information.
> + */
> +
> +/* Type of translation to invalidate (type) */
> +#define H_RPTI_TYPE_NESTED 0x0001 /* Invalidate nested guest partition-scope */
> +#define H_RPTI_TYPE_TLB 0x0002 /* Invalidate TLB */
> +#define H_RPTI_TYPE_PWC 0x0004 /* Invalidate Page Walk Cache */
> +/* Invalidate Process Table Entries if H_RPTI_TYPE_NESTED is clear */
> +#define H_RPTI_TYPE_PRT 0x0008
> +/* Invalidate Partition Table Entries if H_RPTI_TYPE_NESTED is set */
> +#define H_RPTI_TYPE_PAT 0x0008
> +#define H_RPTI_TYPE_ALL (H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC | \
> + H_RPTI_TYPE_PRT)
> +#define H_RPTI_TYPE_NESTED_ALL (H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC | \
> + H_RPTI_TYPE_PAT)
> +
> +/* Invalidation targets (target) */
> +#define H_RPTI_TARGET_CMMU 0x01 /* All virtual processors in the partition */
> +#define H_RPTI_TARGET_CMMU_LOCAL 0x02 /* Current virtual processor */
> +/* All nest/accelerator agents in use by the partition */
> +#define H_RPTI_TARGET_NMMU 0x04
> +
> +/* Page size mask (page sizes) */
> +#define H_RPTI_PAGE_4K 0x01
> +#define H_RPTI_PAGE_64K 0x02
> +#define H_RPTI_PAGE_2M 0x04
> +#define H_RPTI_PAGE_1G 0x08
> +#define H_RPTI_PAGE_ALL (-1UL)
> +
> #ifndef __ASSEMBLY__
> #include <linux/types.h>
>
> diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h
> index 4497c8afb573..a184923abd07 100644
> --- a/arch/powerpc/include/asm/plpar_wrappers.h
> +++ b/arch/powerpc/include/asm/plpar_wrappers.h
> @@ -334,6 +334,49 @@ static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p)
> return rc;
> }
>
> +/*
> + * Wrapper to H_RPT_INVALIDATE hcall that handles return values appropriately
> + *
> + * - Returns H_SUCCESS on success
> + * - For H_BUSY return value, we retry the hcall.
> + * - For any other hcall failures, attempt a full flush once before
> + * resorting to BUG().
> + *
> + * Note: This hcall is expected to fail only very rarely. The correct
> + * error recovery of killing the process/guest will be eventually
> + * needed.
> + */
> +static inline long pseries_rpt_invalidate(u32 pid, u64 target, u64 type,
> + u64 page_sizes, u64 start, u64 end)
> +{
> + long rc;
> + unsigned long all;
> +
> + while (true) {
> + rc = plpar_hcall_norets(H_RPT_INVALIDATE, pid, target, type,
> + page_sizes, start, end);
> + if (rc == H_BUSY) {
> + cpu_relax();
> + continue;
> + } else if (rc == H_SUCCESS)
> + return rc;
> +
> + /* Flush request failed, try with a full flush once */
> + all = (type & H_RPTI_TYPE_NESTED) ? H_RPTI_TYPE_NESTED_ALL :
> + H_RPTI_TYPE_ALL;
> +retry:
> + rc = plpar_hcall_norets(H_RPT_INVALIDATE, pid, target,
> + all, page_sizes, 0, -1UL);
> + if (rc == H_BUSY) {
> + cpu_relax();
> + goto retry;
> + } else if (rc == H_SUCCESS)
> + return rc;
> +
> + BUG();
> + }
> +}
> +
> #else /* !CONFIG_PPC_PSERIES */
>
> static inline long plpar_set_ciabr(unsigned long ciabr)
> @@ -346,6 +389,13 @@ static inline long plpar_pte_read_4(unsigned long flags, unsigned long ptex,
> {
> return 0;
> }
> +
> +static inline long pseries_rpt_invalidate(u32 pid, u64 target, u64 type,
> + u64 page_sizes, u64 start, u64 end)
> +{
> + return 0;
> +}
> +
> #endif /* CONFIG_PPC_PSERIES */
>
> #endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */
> diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c
> index b5cc9b23cf02..180d8ddcf6e3 100644
> --- a/arch/powerpc/mm/book3s64/radix_tlb.c
> +++ b/arch/powerpc/mm/book3s64/radix_tlb.c
> @@ -16,6 +16,7 @@
> #include <asm/tlbflush.h>
> #include <asm/trace.h>
> #include <asm/cputhreads.h>
> +#include <asm/plpar_wrappers.h>
>
> #define RIC_FLUSH_TLB 0
> #define RIC_FLUSH_PWC 1
> @@ -694,7 +695,14 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
> goto local;
> }
>
> - if (cputlb_use_tlbie()) {
> + if (!mmu_has_feature(MMU_FTR_GTSE)) {
> + unsigned long tgt = H_RPTI_TARGET_CMMU;
> +
> + if (atomic_read(&mm->context.copros) > 0)
> + tgt |= H_RPTI_TARGET_NMMU;
> + pseries_rpt_invalidate(pid, tgt, H_RPTI_TYPE_TLB,
> + H_RPTI_PAGE_ALL, 0, -1UL);
> + } else if (cputlb_use_tlbie()) {
> if (mm_needs_flush_escalation(mm))
> _tlbie_pid(pid, RIC_FLUSH_ALL);
> else
> @@ -727,7 +735,16 @@ static void __flush_all_mm(struct mm_struct *mm, bool fullmm)
> goto local;
> }
> }
> - if (cputlb_use_tlbie())
> + if (!mmu_has_feature(MMU_FTR_GTSE)) {
> + unsigned long tgt = H_RPTI_TARGET_CMMU;
> + unsigned long type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
> + H_RPTI_TYPE_PRT;
> +
> + if (atomic_read(&mm->context.copros) > 0)
> + tgt |= H_RPTI_TARGET_NMMU;
> + pseries_rpt_invalidate(pid, tgt, type,
> + H_RPTI_PAGE_ALL, 0, -1UL);
> + } else if (cputlb_use_tlbie())
> _tlbie_pid(pid, RIC_FLUSH_ALL);
> else
> _tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
> @@ -760,7 +777,19 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
> exit_flush_lazy_tlbs(mm);
> goto local;
> }
> - if (cputlb_use_tlbie())
> + if (!mmu_has_feature(MMU_FTR_GTSE)) {
> + unsigned long tgt, page_sizes, size;
> +
> + tgt = H_RPTI_TARGET_CMMU;
> + page_sizes = psize_to_h_rpti(psize);
> + size = 1UL << mmu_psize_to_shift(psize);
> +
> + if (atomic_read(&mm->context.copros) > 0)
> + tgt |= H_RPTI_TARGET_NMMU;
> + pseries_rpt_invalidate(pid, tgt, H_RPTI_TYPE_TLB,
> + page_sizes, vmaddr,
> + vmaddr + size);
> + } else if (cputlb_use_tlbie())
> _tlbie_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
> else
> _tlbiel_va_multicast(mm, vmaddr, pid, psize, RIC_FLUSH_TLB);
> @@ -810,7 +839,14 @@ static inline void _tlbiel_kernel_broadcast(void)
> */
> void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
> {
> - if (cputlb_use_tlbie())
> + if (!mmu_has_feature(MMU_FTR_GTSE)) {
> + unsigned long tgt = H_RPTI_TARGET_CMMU | H_RPTI_TARGET_NMMU;
> + unsigned long type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
> + H_RPTI_TYPE_PRT;
> +
> + pseries_rpt_invalidate(0, tgt, type, H_RPTI_PAGE_ALL,
> + start, end);
> + } else if (cputlb_use_tlbie())
> _tlbie_pid(0, RIC_FLUSH_ALL);
> else
> _tlbiel_kernel_broadcast();
> @@ -864,7 +900,17 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
> nr_pages > tlb_local_single_page_flush_ceiling);
> }
>
> - if (full) {
> + if (!mmu_has_feature(MMU_FTR_GTSE) && !local) {
> + unsigned long tgt = H_RPTI_TARGET_CMMU;
> + unsigned long page_sizes = psize_to_h_rpti(mmu_virtual_psize);
> +
> + if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
> + page_sizes |= psize_to_h_rpti(MMU_PAGE_2M);
> + if (atomic_read(&mm->context.copros) > 0)
> + tgt |= H_RPTI_TARGET_NMMU;
> + pseries_rpt_invalidate(pid, tgt, H_RPTI_TYPE_TLB, page_sizes,
> + start, end);
> + } else if (full) {
> if (local) {
> _tlbiel_pid(pid, RIC_FLUSH_TLB);
> } else {
> @@ -1046,7 +1092,17 @@ static __always_inline void __radix__flush_tlb_range_psize(struct mm_struct *mm,
> nr_pages > tlb_local_single_page_flush_ceiling);
> }
>
> - if (full) {
> + if (!mmu_has_feature(MMU_FTR_GTSE) && !local) {
> + unsigned long tgt = H_RPTI_TARGET_CMMU;
> + unsigned long type = H_RPTI_TYPE_TLB;
> + unsigned long page_sizes = psize_to_h_rpti(psize);
> +
> + if (also_pwc)
> + type |= H_RPTI_TYPE_PWC;
> + if (atomic_read(&mm->context.copros) > 0)
> + tgt |= H_RPTI_TARGET_NMMU;
> + pseries_rpt_invalidate(pid, tgt, type, page_sizes, start, end);
> + } else if (full) {
> if (local) {
> _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB);
> } else {
> @@ -1111,7 +1167,19 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr)
> exit_flush_lazy_tlbs(mm);
> goto local;
> }
> - if (cputlb_use_tlbie())
> + if (!mmu_has_feature(MMU_FTR_GTSE)) {
> + unsigned long tgt, type, page_sizes;
> +
> + tgt = H_RPTI_TARGET_CMMU;
> + type = H_RPTI_TYPE_TLB | H_RPTI_TYPE_PWC |
> + H_RPTI_TYPE_PRT;
> + page_sizes = psize_to_h_rpti(mmu_virtual_psize);
> +
> + if (atomic_read(&mm->context.copros) > 0)
> + tgt |= H_RPTI_TARGET_NMMU;
> + pseries_rpt_invalidate(pid, tgt, type, page_sizes,
> + addr, end);
> + } else if (cputlb_use_tlbie())
> _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true);
> else
> _tlbiel_va_range_multicast(mm,
> --
> 2.21.3
^ permalink raw reply
* Re: [PATCH] ASoC: fsl_asrc: Add an option to select internal ratio mode
From: Shengjiu Wang @ 2020-06-30 5:31 UTC (permalink / raw)
To: Nicolin Chen
Cc: Linux-ALSA, Timur Tabi, Xiubo Li, Fabio Estevam, Shengjiu Wang,
Takashi Iwai, Liam Girdwood, Mark Brown, linuxppc-dev,
linux-kernel
In-Reply-To: <20200629200813.GB27967@Asurada-Nvidia>
On Tue, Jun 30, 2020 at 4:09 AM Nicolin Chen <nicoleotsuka@gmail.com> wrote:
>
> On Mon, Jun 29, 2020 at 09:58:35PM +0800, Shengjiu Wang wrote:
> > The ASRC not only supports ideal ratio mode, but also supports
> > internal ratio mode.
> >
> > For internal rato mode, the rate of clock source should be divided
> > with no remainder by sample rate, otherwise there is sound
> > distortion.
> >
> > Add function fsl_asrc_select_clk() to find proper clock source for
> > internal ratio mode, if the clock source is available then internal
> > ratio mode will be selected.
> >
> > With change, the ideal ratio mode is not the only option for user.
> >
> > Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> > ---
>
> > +static int fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
> > + struct fsl_asrc_pair *pair,
> > + int in_rate,
> > + int out_rate)
> > +{
> > + struct fsl_asrc_pair_priv *pair_priv = pair->private;
> > + struct asrc_config *config = pair_priv->config;
> > + int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
> > + int clk_rate, clk_index;
> > + int i = 0, j = 0;
> > + bool clk_sel[2];
> > +
> > + rate[0] = in_rate;
> > + rate[1] = out_rate;
> > +
> > + /* Select proper clock source for internal ratio mode */
> > + for (j = 0; j < 2; j++) {
> > + for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
> > + clk_index = asrc_priv->clk_map[j][i];
> > + clk_rate = clk_get_rate(asrc_priv->asrck_clk[clk_index]);
>
> + /* Only match a perfect clock source with no remainder */
>
> > + if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
> > + (clk_rate % rate[j]) == 0)
> > + break;
> > + }
> > +
> > + if (i == ASRC_CLK_MAP_LEN) {
> > + select_clk[j] = OUTCLK_ASRCK1_CLK;
> > + clk_sel[j] = false;
> > + } else {
> > + select_clk[j] = i;
> > + clk_sel[j] = true;
> > + }
> > + }
> > +
> > + /* Switch to ideal ratio mode if there is no proper clock source */
> > + if (!clk_sel[IN] || !clk_sel[OUT])
> > + select_clk[IN] = INCLK_NONE;
>
> Could get rid of clk_set:
>
> for (j) {
> for (i) {
> if (match)
> break;
> }
>
> clk[j] = i;
> }
>
> if (clk[IN] == ASRC_CLK_MAP_LEN || clk[OUT] == ASRC_CLK_MAP_LEN)
>
> And it only overrides clk[IN] setting but leaving clk[OUT] to
> to the searching result. This means that clk[OUT] may be using
> a clock source other than OUTCLK_ASRCK1_CLK if sel[IN] happens
> to be false while sel[OUT] happens to be true. Not sure if it
> is intended...but I feel it would probably be safer to use the
> previous settings: INCLK_NONE + OUTCLK_ASRCK1_CLK?
ok, will update the patch.
best regards
wang shengjiu
^ permalink raw reply
* Re: [PATCH 3/3] powerpc/pseries: Add KVM guest doorbell restrictions
From: Nicholas Piggin @ 2020-06-30 5:35 UTC (permalink / raw)
To: Paul Mackerras
Cc: kvm-ppc, Anton Blanchard, Cédric Le Goater, linuxppc-dev,
David Gibson
In-Reply-To: <20200630022713.GA618342@thinks.paulus.ozlabs.org>
Excerpts from Paul Mackerras's message of June 30, 2020 12:27 pm:
> On Sun, Jun 28, 2020 at 01:04:28AM +1000, Nicholas Piggin wrote:
>> KVM guests have certain restrictions and performance quirks when
>> using doorbells. This patch tests for KVM environment in doorbell
>> setup, and optimises IPI performance:
>>
>> - PowerVM guests may now use doorbells even if they are secure.
>>
>> - KVM guests no longer use doorbells if XIVE is available.
>
> It seems, from the fact that you completely remove
> kvm_para_available(), that you perhaps haven't tried building with
> CONFIG_KVM_GUEST=y.
It's still there and builds:
static inline int kvm_para_available(void)
{
return IS_ENABLED(CONFIG_KVM_GUEST) && is_kvm_guest();
}
but...
> Somewhat confusingly, that option is not used or
> needed when building for a PAPR guest (i.e. the "pseries" platform)
> but is used on non-IBM platforms using the "epapr" hypervisor
> interface.
... is_kvm_guest() returns false on !PSERIES now. Not intended
to break EPAPR. I'm not sure of a good way to share this between
EPAPR and PSERIES, I might just make a copy of it but I'll see.
Thanks,
Nick
^ permalink raw reply
* [PATCH 1/4] powerpc/sstep: support new VSX vector paired storage access instructions
From: Balamuruhan S @ 2020-06-30 5:53 UTC (permalink / raw)
To: mpe
Cc: ravi.bangoria, Balamuruhan S, paulus, sandipan, naveen.n.rao,
linuxppc-dev
In-Reply-To: <20200630055307.1154135-1-bala24@linux.ibm.com>
VSX Vector Paired instructions loads/stores an octword (32 bytes)
from/to storage into two sequential VSRs. Add `analyse_instr()` support
to these new instructions,
* Load VSX Vector Paired (lxvp)
* Load VSX Vector Paired Indexed (lxvpx)
* Prefixed Load VSX Vector Paired (plxvp)
* Store VSX Vector Paired (stxvp)
* Store VSX Vector Paired Indexed (stxvpx)
* Prefixed Store VSX Vector Paired (pstxvp)
Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
---
arch/powerpc/lib/sstep.c | 44 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 5abe98216dc2..c92890e71ca7 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -31,6 +31,10 @@ extern char system_call_common[];
#define XER_OV32 0x00080000U
#define XER_CA32 0x00040000U
+#ifdef CONFIG_VSX
+#define VSX_REGISTER_XTP(rd) ((((rd) & 1) << 5) | ((rd) & 0xfe))
+#endif
+
#ifdef CONFIG_PPC_FPU
/*
* Functions in ldstfp.S
@@ -2382,6 +2386,13 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
op->vsx_flags = VSX_SPLAT;
break;
+ case 333: /* lxvpx */
+ op->reg = VSX_REGISTER_XTP(rd);
+ op->type = MKOP(LOAD_VSX, 0, 32);
+ op->element_size = 32;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+
case 364: /* lxvwsx */
op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 4);
@@ -2410,6 +2421,12 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
VSX_CHECK_VEC;
break;
}
+ case 461: /* stxvpx */
+ op->reg = VSX_REGISTER_XTP(rd);
+ op->type = MKOP(STORE_VSX, 0, 32);
+ op->element_size = 32;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
case 524: /* lxsspx */
op->reg = rd | ((word & 1) << 5);
op->type = MKOP(LOAD_VSX, 0, 4);
@@ -2651,6 +2668,21 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
#endif
#ifdef CONFIG_VSX
+ case 6:
+ op->ea = dqform_ea(word, regs);
+ op->reg = VSX_REGISTER_XTP(rd);
+ op->element_size = 32;
+ op->vsx_flags = VSX_CHECK_VEC;
+ switch (word & 0xf) {
+ case 0: /* lxvp */
+ op->type = MKOP(LOAD_VSX, 0, 32);
+ break;
+ case 1: /* stxvp */
+ op->type = MKOP(STORE_VSX, 0, 32);
+ break;
+ }
+ break;
+
case 61: /* stfdp, lxv, stxsd, stxssp, stxv */
switch (word & 7) {
case 0: /* stfdp with LSB of DS field = 0 */
@@ -2779,12 +2811,24 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
case 57: /* pld */
op->type = MKOP(LOAD, PREFIXED, 8);
break;
+ case 58: /* plxvp */
+ op->reg = VSX_REGISTER_XTP(rd);
+ op->type = MKOP(LOAD_VSX, PREFIXED, 32);
+ op->element_size = 32;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
case 60: /* stq */
op->type = MKOP(STORE, PREFIXED, 16);
break;
case 61: /* pstd */
op->type = MKOP(STORE, PREFIXED, 8);
break;
+ case 62: /* pstxvp */
+ op->reg = VSX_REGISTER_XTP(rd);
+ op->type = MKOP(STORE_VSX, PREFIXED, 32);
+ op->element_size = 32;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
}
break;
case 1: /* Type 01 Eight-Byte Register-to-Register */
base-commit: 64677779e8962c20b580b471790fe42367750599
--
2.24.1
^ permalink raw reply related
* [PATCH 0/4] VSX 32-byte vector paired load/store instructions
From: Balamuruhan S @ 2020-06-30 5:53 UTC (permalink / raw)
To: mpe
Cc: ravi.bangoria, Balamuruhan S, paulus, sandipan, naveen.n.rao,
linuxppc-dev
VSX vector paired instructions operates with octword (32-byte) operand
for loads and stores between storage and a pair of two sequential Vector-Scalar
Registers (VSRs). There are 4 word instructions and 2 prefixed instructions
that provides this 32-byte storage access operations - lxvp, lxvpx, stxvp,
stxvpx, plxvpx, pstxvpx.
Emulation infrastructure doesn't have support for these instructions, to
operate with 32-byte storage access and to operate with 2 VSX registers.
This patch series enables the instruction emulation support and adds test
cases for them respectively.
Balamuruhan S (4):
powerpc/sstep: support new VSX vector paired storage access
instructions
powerpc/sstep: support emulation for vsx vector paired storage access
instructions
powerpc ppc-opcode: add opcodes for vsx vector paired instructions
powerpc sstep: add testcases for vsx load/store instructions
arch/powerpc/include/asm/ppc-opcode.h | 11 ++
arch/powerpc/include/asm/sstep.h | 2 +-
arch/powerpc/lib/sstep.c | 102 +++++++++-
arch/powerpc/lib/test_emulate_step.c | 273 ++++++++++++++++++++++++++
4 files changed, 378 insertions(+), 10 deletions(-)
base-commit: 64677779e8962c20b580b471790fe42367750599
--
2.24.1
^ permalink raw reply
* [PATCH 2/4] powerpc/sstep: support emulation for vsx vector paired storage access instructions
From: Balamuruhan S @ 2020-06-30 5:53 UTC (permalink / raw)
To: mpe
Cc: ravi.bangoria, Balamuruhan S, paulus, sandipan, naveen.n.rao,
linuxppc-dev
In-Reply-To: <20200630055307.1154135-1-bala24@linux.ibm.com>
add emulate_step() changes to support vsx vector paired storage
access instructions that provides octword operands loads/stores
between storage and set of 64 Vector Scalar Registers (VSRs).
Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
---
arch/powerpc/include/asm/sstep.h | 2 +-
arch/powerpc/lib/sstep.c | 58 +++++++++++++++++++++++++++-----
2 files changed, 50 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
index 3b01c69a44aa..a6c0b299bcc9 100644
--- a/arch/powerpc/include/asm/sstep.h
+++ b/arch/powerpc/include/asm/sstep.h
@@ -126,7 +126,7 @@ union vsx_reg {
unsigned long d[2];
float fp[4];
double dp[2];
- __vector128 v;
+ __vector128 v[2];
};
/*
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index c92890e71ca7..74c730cae7d8 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -279,6 +279,19 @@ static nokprobe_inline void do_byte_reverse(void *ptr, int nb)
up[1] = tmp;
break;
}
+ case 32: {
+ unsigned long *up = (unsigned long *)ptr;
+ unsigned long tmp;
+
+ tmp = byterev_8(up[0]);
+ up[0] = byterev_8(up[3]);
+ up[3] = tmp;
+ tmp = byterev_8(up[2]);
+ up[2] = byterev_8(up[1]);
+ up[1] = tmp;
+ break;
+ }
+
#endif
default:
WARN_ON_ONCE(1);
@@ -709,6 +722,8 @@ void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
reg->d[0] = reg->d[1] = 0;
switch (op->element_size) {
+ case 32:
+ /* [p]lxvp[x] or [p]stxvp[x] */
case 16:
/* whole vector; lxv[x] or lxvl[l] */
if (size == 0)
@@ -717,7 +732,7 @@ void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
if (IS_LE && (op->vsx_flags & VSX_LDLEFT))
rev = !rev;
if (rev)
- do_byte_reverse(reg, 16);
+ do_byte_reverse(reg, size);
break;
case 8:
/* scalar loads, lxvd2x, lxvdsx */
@@ -793,6 +808,22 @@ void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
size = GETSIZE(op->type);
switch (op->element_size) {
+ case 32:
+ /* [p]lxvp[x] or [p]stxvp[x] */
+ if (size == 0)
+ break;
+ if (IS_LE && (op->vsx_flags & VSX_LDLEFT))
+ rev = !rev;
+ if (rev) {
+ /* reverse 32 bytes */
+ buf.d[0] = byterev_8(reg->d[3]);
+ buf.d[1] = byterev_8(reg->d[2]);
+ buf.d[2] = byterev_8(reg->d[1]);
+ buf.d[3] = byterev_8(reg->d[0]);
+ reg = &buf;
+ }
+ memcpy(mem, reg, size);
+ break;
case 16:
/* stxv, stxvx, stxvl, stxvll */
if (size == 0)
@@ -861,28 +892,33 @@ static nokprobe_inline int do_vsx_load(struct instruction_op *op,
bool cross_endian)
{
int reg = op->reg;
- u8 mem[16];
+ int i, nr_vsx_regs;
+ u8 mem[32];
union vsx_reg buf;
int size = GETSIZE(op->type);
if (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size, regs))
return -EFAULT;
+ nr_vsx_regs = size / sizeof(__vector128);
emulate_vsx_load(op, &buf, mem, cross_endian);
preempt_disable();
if (reg < 32) {
/* FP regs + extensions */
if (regs->msr & MSR_FP) {
- load_vsrn(reg, &buf);
+ for (i = 0; i < nr_vsx_regs; i++)
+ load_vsrn(reg + i, &buf.v[i]);
} else {
current->thread.fp_state.fpr[reg][0] = buf.d[0];
current->thread.fp_state.fpr[reg][1] = buf.d[1];
}
} else {
if (regs->msr & MSR_VEC)
- load_vsrn(reg, &buf);
+ for (i = 0; i < nr_vsx_regs; i++)
+ load_vsrn(reg + i, &buf.v[i]);
+
else
- current->thread.vr_state.vr[reg - 32] = buf.v;
+ current->thread.vr_state.vr[reg - 32] = buf.v[0];
}
preempt_enable();
return 0;
@@ -893,27 +929,31 @@ static nokprobe_inline int do_vsx_store(struct instruction_op *op,
bool cross_endian)
{
int reg = op->reg;
- u8 mem[16];
+ int i, nr_vsx_regs;
+ u8 mem[32];
union vsx_reg buf;
int size = GETSIZE(op->type);
if (!address_ok(regs, ea, size))
return -EFAULT;
+ nr_vsx_regs = size / sizeof(__vector128);
preempt_disable();
if (reg < 32) {
/* FP regs + extensions */
if (regs->msr & MSR_FP) {
- store_vsrn(reg, &buf);
+ for (i = 0; i < nr_vsx_regs; i++)
+ store_vsrn(reg + i, &buf.v[i]);
} else {
buf.d[0] = current->thread.fp_state.fpr[reg][0];
buf.d[1] = current->thread.fp_state.fpr[reg][1];
}
} else {
if (regs->msr & MSR_VEC)
- store_vsrn(reg, &buf);
+ for (i = 0; i < nr_vsx_regs; i++)
+ store_vsrn(reg + i, &buf.v[i]);
else
- buf.v = current->thread.vr_state.vr[reg - 32];
+ buf.v[0] = current->thread.vr_state.vr[reg - 32];
}
preempt_enable();
emulate_vsx_store(op, &buf, mem, cross_endian);
--
2.24.1
^ permalink raw reply related
* [PATCH 3/4] powerpc ppc-opcode: add opcodes for vsx vector paired instructions
From: Balamuruhan S @ 2020-06-30 5:53 UTC (permalink / raw)
To: mpe
Cc: ravi.bangoria, Balamuruhan S, paulus, sandipan, naveen.n.rao,
linuxppc-dev
In-Reply-To: <20200630055307.1154135-1-bala24@linux.ibm.com>
add instruction opcodes for new vsx vector paired instructions,
* Load VSX Vector Paired (lxvp)
* Load VSX Vector Paired Indexed (lxvpx)
* Store VSX Vector Paired (stxvp)
* Store VSX Vector Paired Indexed (stxvpx)
Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
---
arch/powerpc/include/asm/ppc-opcode.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 2a39c716c343..558efd25683b 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -210,6 +210,10 @@
#define PPC_INST_ISEL 0x7c00001e
#define PPC_INST_ISEL_MASK 0xfc00003e
#define PPC_INST_LDARX 0x7c0000a8
+#define PPC_INST_LXVP 0x18000000
+#define PPC_INST_LXVPX 0x7c00029a
+#define PPC_INST_STXVP 0x18000001
+#define PPC_INST_STXVPX 0x7c00039a
#define PPC_INST_STDCX 0x7c0001ad
#define PPC_INST_LQARX 0x7c000228
#define PPC_INST_STQCX 0x7c00016d
--
2.24.1
^ permalink raw reply related
* [PATCH 4/4] powerpc sstep: add testcases for vsx load/store instructions
From: Balamuruhan S @ 2020-06-30 5:53 UTC (permalink / raw)
To: mpe
Cc: ravi.bangoria, Balamuruhan S, paulus, sandipan, naveen.n.rao,
linuxppc-dev
In-Reply-To: <20200630055307.1154135-1-bala24@linux.ibm.com>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=n, Size: 9569 bytes --]
add testcases for vsx load/store vector paired instructions,
* Load VSX Vector Paired (lxvp)
* Load VSX Vector Paired Indexed (lxvpx)
* Prefixed Load VSX Vector Paired (plxvp)
* Store VSX Vector Paired (stxvp)
* Store VSX Vector Paired Indexed (stxvpx)
* Prefixed Store VSX Vector Paired (pstxvp)
Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
---
arch/powerpc/include/asm/ppc-opcode.h | 7 +
arch/powerpc/lib/test_emulate_step.c | 273 ++++++++++++++++++++++++++
2 files changed, 280 insertions(+)
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 558efd25683b..9bc9b184db6e 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -384,6 +384,10 @@
#define PPC_INST_VCMPEQUD 0x100000c7
#define PPC_INST_VCMPEQUB 0x10000006
+/* Prefixes */
+#define PPC_PREFIX_MLS 0x06000000
+#define PPC_PREFIX_8LS 0x04000000
+
/* macros to insert fields into opcodes */
#define ___PPC_RA(a) (((a) & 0x1f) << 16)
#define ___PPC_RB(b) (((b) & 0x1f) << 11)
@@ -415,6 +419,9 @@
#define __PPC_CT(t) (((t) & 0x0f) << 21)
#define __PPC_SPR(r) ((((r) & 0x1f) << 16) | ((((r) >> 5) & 0x1f) << 11))
#define __PPC_RC21 (0x1 << 10)
+#define __PPC_PRFX_R(r) (((r) & 0x1) << 20)
+#define __PPC_TP(tp) (((tp) & 0xf) << 22)
+#define __PPC_TX(tx) (((tx) & 0x1) << 21)
/*
* Both low and high 16 bits are added as SIGNED additions, so if low 16 bits
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c
index 46af80279ebc..98ecbc66bef8 100644
--- a/arch/powerpc/lib/test_emulate_step.c
+++ b/arch/powerpc/lib/test_emulate_step.c
@@ -14,7 +14,13 @@
#include <asm/inst.h>
#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
+#define IMM_H(i) (((uintptr_t)(i) >> 16) & 0x3ffff)
#define IMM_DS(i) ((uintptr_t)(i) & 0xfffc)
+#define IMM_DQ(i) (((uintptr_t)(i) & 0xfff) << 4)
+
+#define PLXVP_EX_OP 0xe8000000
+#define PSTXVP_EX_OP 0xf8000000
+
/*
* Defined with TEST_ prefix so it does not conflict with other
@@ -47,6 +53,21 @@
___PPC_RA(a) | ___PPC_RB(b))
#define TEST_LXVD2X(s, a, b) ppc_inst(PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
#define TEST_STXVD2X(s, a, b) ppc_inst(PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
+#define TEST_LXVP(tp, tx, a, i) \
+ (PPC_INST_LXVP | __PPC_TP(tp) | __PPC_TX(tx) | ___PPC_RA(a) | IMM_DQ(i))
+#define TEST_STXVP(sp, sx, a, i) \
+ (PPC_INST_STXVP | __PPC_TP(sp) | __PPC_TX(sx) | ___PPC_RA(a) | IMM_DQ(i) | 0x1)
+#define TEST_LXVPX(tp, tx, a, b) \
+ (PPC_INST_LXVPX | __PPC_TP(tp) | __PPC_TX(tx) | ___PPC_RA(a) | ___PPC_RB(b))
+#define TEST_STXVPX(sp, sx, a, b) \
+ (PPC_INST_STXVPX | __PPC_TP(sp) | __PPC_TX(sx) | ___PPC_RA(a) | ___PPC_RB(b))
+#define TEST_PLXVP(a, i, pr, tp, tx) \
+ ((PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i)) << 32 | \
+ (PLXVP_EX_OP | __PPC_TP(tp) | __PPC_TX(tx) | ___PPC_RA(a) | IMM_L(i)))
+#define TEST_PSTXVP(a, i, pr, sp, sx) \
+ ((PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i)) << 32 | \
+ (PSTXVP_EX_OP | __PPC_TP(sp) | __PPC_TX(sx) | ___PPC_RA(a) | IMM_L(i)))
+
#define TEST_ADD(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) | \
___PPC_RA(a) | ___PPC_RB(b))
#define TEST_ADD_DOT(t, a, b) ppc_inst(PPC_INST_ADD | ___PPC_RT(t) | \
@@ -444,6 +465,255 @@ static void __init test_lxvd2x_stxvd2x(void)
}
#endif /* CONFIG_VSX */
+#ifdef CONFIG_VSX
+static void __init test_lxvp_stxvp(void)
+{
+ struct pt_regs regs;
+ union {
+ vector128 a[2];
+ u32 b[8];
+ } c;
+ u32 cached_b[8];
+ int stepped = -1;
+
+ init_pt_regs(®s);
+
+ /*** lxvp ***/
+
+ cached_b[0] = c.b[0] = 18233;
+ cached_b[1] = c.b[1] = 34863571;
+ cached_b[2] = c.b[2] = 834;
+ cached_b[3] = c.b[3] = 6138911;
+ cached_b[4] = c.b[4] = 1234;
+ cached_b[5] = c.b[5] = 5678;
+ cached_b[6] = c.b[6] = 91011;
+ cached_b[7] = c.b[7] = 121314;
+
+ regs.gpr[4] = (unsigned long)&c.a;
+
+ /*
+ * lxvp XTp,DQ(RA)
+ * XTp = 32×TX + 2×Tp
+ * let TX=1 Tp=1 RA=4 DQ=0
+ */
+ stepped = emulate_step(®s, ppc_inst(TEST_LXVP(1, 1, 4, 0)));
+
+ if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
+ show_result("lxvp", "PASS");
+ } else {
+ if (!cpu_has_feature(CPU_FTR_VSX))
+ show_result("lxvp", "PASS (!CPU_FTR_VSX)");
+ else
+ show_result("lxvp", "FAIL");
+ }
+
+ /*** stxvp ***/
+
+ c.b[0] = 21379463;
+ c.b[1] = 87;
+ c.b[2] = 374234;
+ c.b[3] = 4;
+ c.b[4] = 90;
+ c.b[5] = 122;
+ c.b[6] = 555;
+ c.b[7] = 32144;
+
+ /*
+ * stxvp XSp,DQ(RA)
+ * XSp = 32×SX + 2×Sp
+ * let SX=1 Sp=1 RA=4 DQ=0
+ */
+ stepped = emulate_step(®s, ppc_inst(TEST_STXVP(1, 1, 4, 0)));
+
+ if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
+ cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
+ cached_b[4] == c.b[4] && cached_b[5] == c.b[5] &&
+ cached_b[6] == c.b[6] && cached_b[7] == c.b[7] &&
+ cpu_has_feature(CPU_FTR_VSX)) {
+ show_result("stxvp", "PASS");
+ } else {
+ if (!cpu_has_feature(CPU_FTR_VSX))
+ show_result("stxvp", "PASS (!CPU_FTR_VSX)");
+ else
+ show_result("stxvp", "FAIL");
+ }
+}
+#else
+static void __init test_lxvp_stxvp(void)
+{
+ show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
+ show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
+}
+#endif /* CONFIG_VSX */
+
+#ifdef CONFIG_VSX
+static void __init test_lxvpx_stxvpx(void)
+{
+ struct pt_regs regs;
+ union {
+ vector128 a[2];
+ u32 b[8];
+ } c;
+ u32 cached_b[8];
+ int stepped = -1;
+
+ init_pt_regs(®s);
+
+ /*** lxvpx ***/
+
+ cached_b[0] = c.b[0] = 18233;
+ cached_b[1] = c.b[1] = 34863571;
+ cached_b[2] = c.b[2] = 834;
+ cached_b[3] = c.b[3] = 6138911;
+ cached_b[4] = c.b[4] = 1234;
+ cached_b[5] = c.b[5] = 5678;
+ cached_b[6] = c.b[6] = 91011;
+ cached_b[7] = c.b[7] = 121314;
+
+ regs.gpr[3] = (unsigned long)&c.a;
+ regs.gpr[4] = 0;
+
+ /*
+ * lxvpx XTp,RA,RB
+ * XTp = 32×TX + 2×Tp
+ * let TX=1 Tp=1 RA=3 RB=4
+ */
+ stepped = emulate_step(®s, ppc_inst(TEST_LXVPX(1, 1, 3, 4)));
+
+ if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
+ show_result("lxvpx", "PASS");
+ } else {
+ if (!cpu_has_feature(CPU_FTR_VSX))
+ show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
+ else
+ show_result("lxvpx", "FAIL");
+ }
+
+ /*** stxvpx ***/
+
+ c.b[0] = 21379463;
+ c.b[1] = 87;
+ c.b[2] = 374234;
+ c.b[3] = 4;
+ c.b[4] = 90;
+ c.b[5] = 122;
+ c.b[6] = 555;
+ c.b[7] = 32144;
+
+ /*
+ * stxvpx XSp,RA,RB
+ * XSp = 32×SX + 2×Sp
+ * let SX=1 Sp=1 RA=3 RB=4
+ */
+ stepped = emulate_step(®s, ppc_inst(TEST_STXVPX(1, 1, 3, 4)));
+
+ if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
+ cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
+ cached_b[4] == c.b[4] && cached_b[5] == c.b[5] &&
+ cached_b[6] == c.b[6] && cached_b[7] == c.b[7] &&
+ cpu_has_feature(CPU_FTR_VSX)) {
+ show_result("stxvpx", "PASS");
+ } else {
+ if (!cpu_has_feature(CPU_FTR_VSX))
+ show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
+ else
+ show_result("stxvpx", "FAIL");
+ }
+}
+#else
+static void __init test_lxvpx_stxvpx(void)
+{
+ show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
+ show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
+}
+#endif /* CONFIG_VSX */
+
+#ifdef CONFIG_VSX
+static void __init test_plxvp_pstxvp(void)
+{
+ struct ppc_inst instr;
+ struct pt_regs regs;
+ union {
+ vector128 a[2];
+ u32 b[8];
+ } c;
+ u32 cached_b[8];
+ int stepped = -1;
+
+ /*
+ * plxvp XTp,D(RA),R
+ * XSp = 32×SX + 2×Sp
+ * let RA=3 R=0 D=d0||d1=0 R=0 Sp=1 SX=1
+ */
+ instr = ppc_inst_prefix(TEST_PLXVP(3, 0, 0, 1, 1) >> 32,
+ TEST_PLXVP(3, 0, 0, 1, 1) & 0xffffffff);
+
+ /*** plxvpx ***/
+
+ cached_b[0] = c.b[0] = 18233;
+ cached_b[1] = c.b[1] = 34863571;
+ cached_b[2] = c.b[2] = 834;
+ cached_b[3] = c.b[3] = 6138911;
+ cached_b[4] = c.b[4] = 1234;
+ cached_b[5] = c.b[5] = 5678;
+ cached_b[6] = c.b[6] = 91011;
+ cached_b[7] = c.b[7] = 121314;
+
+ init_pt_regs(®s);
+ regs.gpr[3] = (unsigned long)&c.a;
+
+ stepped = emulate_step(®s, instr);
+ if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
+ show_result("plxvpx", "PASS");
+ } else {
+ if (!cpu_has_feature(CPU_FTR_VSX))
+ show_result("plxvpx", "PASS (!CPU_FTR_VSX)");
+ else
+ show_result("plxvpx", "FAIL");
+ }
+
+ /*** pstxvpx ***/
+
+ c.b[0] = 21379463;
+ c.b[1] = 87;
+ c.b[2] = 374234;
+ c.b[3] = 4;
+ c.b[4] = 90;
+ c.b[5] = 122;
+ c.b[6] = 555;
+ c.b[7] = 32144;
+
+ /*
+ * pstxvpx XTp,D(RA),R
+ * XSp = 32×SX + 2×Sp
+ * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
+ */
+ instr = ppc_inst_prefix(TEST_PSTXVP(3, 0, 0, 1, 1) >> 32,
+ TEST_PSTXVP(3, 0, 0, 1, 1) & 0xffffffff);
+
+ stepped = emulate_step(®s, instr);
+
+ if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
+ cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
+ cached_b[4] == c.b[4] && cached_b[5] == c.b[5] &&
+ cached_b[6] == c.b[6] && cached_b[7] == c.b[7] &&
+ cpu_has_feature(CPU_FTR_VSX)) {
+ show_result("pstxvpx", "PASS");
+ } else {
+ if (!cpu_has_feature(CPU_FTR_VSX))
+ show_result("pstxvpx", "PASS (!CPU_FTR_VSX)");
+ else
+ show_result("pstxvpx", "FAIL");
+ }
+}
+#else
+static void __init test_plxvp_pstxvp(void)
+{
+ show_result("plxvpx", "SKIP (CONFIG_VSX is not set)");
+ show_result("pstxvpx", "SKIP (CONFIG_VSX is not set)");
+}
+#endif /* CONFIG_VSX */
+
static void __init run_tests_load_store(void)
{
test_ld();
@@ -455,6 +725,9 @@ static void __init run_tests_load_store(void)
test_lfdx_stfdx();
test_lvx_stvx();
test_lxvd2x_stxvd2x();
+ test_lxvp_stxvp();
+ test_lxvpx_stxvpx();
+ test_plxvp_pstxvp();
}
struct compute_test {
--
2.24.1
^ permalink raw reply related
* Re: [PATCH v4 7/8] lockdep: Change hardirq{s_enabled,_context} to per-cpu variables
From: Ahmed S. Darwish @ 2020-06-30 5:59 UTC (permalink / raw)
To: Peter Zijlstra
Cc: linux-s390, linuxppc-dev, bigeasy, x86, heiko.carstens,
linux-kernel, rostedt, davem, sparclinux, linux, tglx, will,
mingo
In-Reply-To: <20200623083721.512673481@infradead.org>
Peter Zijlstra wrote:
...
> -#define lockdep_assert_irqs_disabled() do { \
> - WARN_ONCE(debug_locks && !current->lockdep_recursion && \
> - current->hardirqs_enabled, \
> - "IRQs not disabled as expected\n"); \
> - } while (0)
...
> +#define lockdep_assert_irqs_disabled() \
> +do { \
> + WARN_ON_ONCE(debug_locks && this_cpu_read(hardirqs_enabled)); \
> +} while (0)
I think it would be nice to keep the "IRQs not disabled as expected"
message. It makes the lockdep splat much more readable.
This is similarly the case for the v3 lockdep preemption macros:
https://lkml.kernel.org/r/20200630054452.3675847-5-a.darwish@linutronix.de
I did not add a message though to get in-sync with the IRQ macros above.
Thanks,
--
Ahmed S. Darwish
Linutronix GmbH
^ permalink raw reply
* Re: [PATCH 04/11] ppc64/kexec_file: avoid stomping memory used by special regions
From: Hari Bathini @ 2020-06-30 6:10 UTC (permalink / raw)
To: piliu, Michael Ellerman, Andrew Morton
Cc: Kexec-ml, Petr Tesarik, Mahesh J Salgaonkar, Sourabh Jain, lkml,
linuxppc-dev, Mimi Zohar, Vivek Goyal, Dave Young,
Thiago Jung Bauermann, Eric Biederman
In-Reply-To: <283fc181-2331-7c2f-db66-5e02e5ffb2e4@redhat.com>
On 30/06/20 9:00 am, piliu wrote:
>
>
> On 06/29/2020 01:55 PM, Hari Bathini wrote:
>>
>>
>> On 28/06/20 7:44 am, piliu wrote:
>>> Hi Hari,
>>
>> Hi Pingfan,
>>
>>>
>>> After a quick through for this series, I have a few question/comment on
>>> this patch for the time being. Pls see comment inline.
>>>
>>> On 06/27/2020 03:05 AM, Hari Bathini wrote:
>>>> crashkernel region could have an overlap with special memory regions
>>>> like opal, rtas, tce-table & such. These regions are referred to as
>>>> exclude memory ranges. Setup this ranges during image probe in order
>>>> to avoid them while finding the buffer for different kdump segments.
>>
>> [...]
>>
>>>> + /*
>>>> + * Use the locate_mem_hole logic in kexec_add_buffer() for regular
>>>> + * kexec_file_load syscall
>>>> + */
>>>> + if (kbuf->image->type != KEXEC_TYPE_CRASH)
>>>> + return 0;
>>> Can the ranges overlap [crashk_res.start, crashk_res.end]? Otherwise
>>> there is no requirement for @exclude_ranges.
>>
>> The ranges like rtas, opal are loaded by f/w. They almost always overlap with
>> crashkernel region. So, @exclude_ranges is required to support kdump.
> f/w passes rtas/opal as service, then must f/w mark these ranges as
> fdt_reserved_mem in order to make kernel aware not to use these ranges?
It does. Actually, reserve_map + reserved-ranges are reserved as soon as
memblock allocator is ready but not before crashkernel reservation.
Check early_reserve_mem() call in kernel/prom.c
> Otherwise kernel memory allocation besides kdump can also overwrite
> these ranges.>
> Hmm, revisiting reserve_crashkernel(). It seems not to take any reserved
> memory into consider except kernel text. Could it work based on memblock
> allocator?
So, kdump could possibly overwrite these regions which is why an exclude
range list is needed. Same thing was done in kexec-tools as well.
Thanks
Hari
^ permalink raw reply
* Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
From: Dan Williams @ 2020-06-30 7:06 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: Jan Kara, linux-nvdimm, Jeff Moyer, Oliver O'Halloran,
Michal Suchánek, linuxppc-dev
In-Reply-To: <87imf9gn9w.fsf@linux.ibm.com>
On Mon, Jun 29, 2020 at 10:02 PM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> Dan Williams <dan.j.williams@intel.com> writes:
>
> > On Mon, Jun 29, 2020 at 1:29 PM Aneesh Kumar K.V
> > <aneesh.kumar@linux.ibm.com> wrote:
> >>
> >> Architectures like ppc64 provide persistent memory specific barriers
> >> that will ensure that all stores for which the modifications are
> >> written to persistent storage by preceding dcbfps and dcbstps
> >> instructions have updated persistent storage before any data
> >> access or data transfer caused by subsequent instructions is initiated.
> >> This is in addition to the ordering done by wmb()
> >>
> >> Update nvdimm core such that architecture can use barriers other than
> >> wmb to ensure all previous writes are architecturally visible for
> >> the platform buffer flush.
> >>
> >> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> >> ---
> >> drivers/md/dm-writecache.c | 2 +-
> >> drivers/nvdimm/region_devs.c | 8 ++++----
> >> include/linux/libnvdimm.h | 4 ++++
> >> 3 files changed, 9 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
> >> index 74f3c506f084..8c6b6dce64e2 100644
> >> --- a/drivers/md/dm-writecache.c
> >> +++ b/drivers/md/dm-writecache.c
> >> @@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)
> >> static void writecache_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
> >> {
> >> if (WC_MODE_PMEM(wc))
> >> - wmb();
> >> + arch_pmem_flush_barrier();
> >> else
> >> ssd_commit_flushed(wc, wait_for_ios);
> >> }
> >> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> >> index 4502f9c4708d..b308ad09b63d 100644
> >> --- a/drivers/nvdimm/region_devs.c
> >> +++ b/drivers/nvdimm/region_devs.c
> >> @@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region)
> >> idx = this_cpu_add_return(flush_idx, hash_32(current->pid + idx, 8));
> >>
> >> /*
> >> - * The first wmb() is needed to 'sfence' all previous writes
> >> - * such that they are architecturally visible for the platform
> >> - * buffer flush. Note that we've already arranged for pmem
> >> + * The first arch_pmem_flush_barrier() is needed to 'sfence' all
> >> + * previous writes such that they are architecturally visible for
> >> + * the platform buffer flush. Note that we've already arranged for pmem
> >> * writes to avoid the cache via memcpy_flushcache(). The final
> >> * wmb() ensures ordering for the NVDIMM flush write.
> >> */
> >> - wmb();
> >> + arch_pmem_flush_barrier();
> >> for (i = 0; i < nd_region->ndr_mappings; i++)
> >> if (ndrd_get_flush_wpq(ndrd, i, 0))
> >> writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));
> >> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> >> index 18da4059be09..66f6c65bd789 100644
> >> --- a/include/linux/libnvdimm.h
> >> +++ b/include/linux/libnvdimm.h
> >> @@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size)
> >> }
> >> #endif
> >>
> >> +#ifndef arch_pmem_flush_barrier
> >> +#define arch_pmem_flush_barrier() wmb()
> >> +#endif
> >
> > I think it is out of place to define this in libnvdimm.h and it is odd
> > to give it such a long name. The other pmem api helpers like
> > arch_wb_cache_pmem() and arch_invalidate_pmem() are function calls for
> > libnvdimm driver operations, this barrier is just an instruction and
> > is closer to wmb() than the pmem api routine.
> >
> > Since it is a store fence for pmem, so let's just call it pmem_wmb()
> > and define the generic version in include/linux/compiler.h. It should
> > probably also be documented alongside dma_wmb() in
> > Documentation/memory-barriers.txt about why code would use it over
> > wmb(), and why a symmetric pmem_rmb() is not needed.
>
> How about the below? I used pmem_barrier() instead of pmem_wmb().
Why? A barrier() is a bi-directional ordering mechanic for reads and
writes, and the proposed semantics mechanism only orders writes +
persistence. Otherwise the default fallback to wmb() on archs that
don't override it does not make sense.
> I
> guess we wanted this to order() any data access not jus the following
> stores to persistent storage?
Why?
> W.r.t why a symmetric pmem_rmb() is not
> needed I was not sure how to explain that. Are you suggesting to explain
> why a read/load from persistent storage don't want to wait for
> pmem_barrier() ?
I would expect that the explanation is that a typical rmb() is
sufficient and that there is nothing pmem specific semantic for read
ordering for pmem vs normal read-barrier semantics.
>
> modified Documentation/memory-barriers.txt
> @@ -1935,6 +1935,16 @@ There are some more advanced barrier functions:
> relaxed I/O accessors and the Documentation/DMA-API.txt file for more
> information on consistent memory.
>
> + (*) pmem_barrier();
> +
> + These are for use with persistent memory to esure the ordering of stores
> + to persistent memory region.
If it was just ordering I would expect a typical wmb() to be
sufficient, why is the pmem-specific instruction needed? I thought it
was handshaking with hardware to ensure acceptance into a persistence
domain *in addition* to ordering the stores.
> + For example, after a non temporal write to persistent storage we use pmem_barrier()
> + to ensures that stores have updated the persistent storage before
> + any data access or data transfer caused by subsequent instructions is initiated.
Isn't the ordering aspect is irrelevant relative to traditional wmb()?
For example if you used the wrong sync instruction the store ordering
will still be correct it would just not persist at the same time as
barrier completes. Or am I misunderstanding how these new instructions
are distinct?
> +
>
> ===============================
> IMPLICIT KERNEL MEMORY BARRIERS
> modified arch/powerpc/include/asm/barrier.h
> @@ -97,6 +97,19 @@ do { \
> #define barrier_nospec()
> #endif /* CONFIG_PPC_BARRIER_NOSPEC */
>
> +/*
> + * pmem_barrier() ensures that all stores for which the modification
> + * are written to persistent storage by preceding dcbfps/dcbstps
> + * instructions have updated persistent storage before any data
> + * access or data transfer caused by subsequent instructions is
> + * initiated.
> + */
> +#define pmem_barrier pmem_barrier
> +static inline void pmem_barrier(void)
> +{
> + asm volatile(PPC_PHWSYNC ::: "memory");
> +}
> +
> #include <asm-generic/barrier.h>
>
> #endif /* _ASM_POWERPC_BARRIER_H */
> modified include/asm-generic/barrier.h
> @@ -257,5 +257,16 @@ do { \
> })
> #endif
>
> +/*
> + * pmem_barrier() ensures that all stores for which the modification
> + * are written to persistent storage by preceding instructions have
> + * updated persistent storage before any data access or data transfer
> + * caused by subsequent instructions is
> + * initiated.
> + */
> +#ifndef pmem_barrier
> +#define pmem_barrier wmb()
> +#endif
> +
> #endif /* !__ASSEMBLY__ */
> #endif /* __ASM_GENERIC_BARRIER_H */
>
^ permalink raw reply
* Re: [PATCH v6 5/8] powerpc/pmem/of_pmem: Update of_pmem to use the new barrier instruction.
From: Dan Williams @ 2020-06-30 7:16 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: Jan Kara, Michal Suchánek, linuxppc-dev, linux-nvdimm
In-Reply-To: <87ftadgn3r.fsf@linux.ibm.com>
On Mon, Jun 29, 2020 at 10:05 PM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> Dan Williams <dan.j.williams@intel.com> writes:
>
> > On Mon, Jun 29, 2020 at 6:58 AM Aneesh Kumar K.V
> > <aneesh.kumar@linux.ibm.com> wrote:
> >>
> >> of_pmem on POWER10 can now use phwsync instead of hwsync to ensure
> >> all previous writes are architecturally visible for the platform
> >> buffer flush.
> >>
> >> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> >> ---
> >> arch/powerpc/include/asm/cacheflush.h | 7 +++++++
> >> 1 file changed, 7 insertions(+)
> >>
> >> diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
> >> index 54764c6e922d..95782f77d768 100644
> >> --- a/arch/powerpc/include/asm/cacheflush.h
> >> +++ b/arch/powerpc/include/asm/cacheflush.h
> >> @@ -98,6 +98,13 @@ static inline void invalidate_dcache_range(unsigned long start,
> >> mb(); /* sync */
> >> }
> >>
> >> +#define arch_pmem_flush_barrier arch_pmem_flush_barrier
> >> +static inline void arch_pmem_flush_barrier(void)
> >> +{
> >> + if (cpu_has_feature(CPU_FTR_ARCH_207S))
> >> + asm volatile(PPC_PHWSYNC ::: "memory");
> >
> > Shouldn't this fallback to a compatible store-fence in an else statement?
>
> The idea was to avoid calling this on anything else. We ensure that by
> making sure that pmem devices are not initialized on systems without that
> cpu feature. Patch 1 does that. Also, the last patch adds a WARN_ON() to
> catch the usage of this outside pmem devices and on systems without that
> cpu feature.
If patch1 handles this why re-check the cpu-feature in this helper? If
the intent is for these routines to be generic why not have them fall
back to the P8 barrier instructions for example like x86 clwb(). Any
kernel code can call it, and it falls back to a compatible clflush()
call on older cpus. I otherwise don't get the point of patch7.
^ permalink raw reply
* Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
From: Aneesh Kumar K.V @ 2020-06-30 7:22 UTC (permalink / raw)
To: Dan Williams
Cc: Jan Kara, linux-nvdimm, Jeff Moyer, Oliver O'Halloran,
Michal Suchánek, linuxppc-dev
In-Reply-To: <CAPcyv4hbECX+7cvX+eT97jvDFUTjQbUEqExZKpV_moDWMFzJ6A@mail.gmail.com>
On 6/30/20 12:36 PM, Dan Williams wrote:
> On Mon, Jun 29, 2020 at 10:02 PM Aneesh Kumar K.V
> <aneesh.kumar@linux.ibm.com> wrote:
>>
>> Dan Williams <dan.j.williams@intel.com> writes:
>>
>>> On Mon, Jun 29, 2020 at 1:29 PM Aneesh Kumar K.V
>>> <aneesh.kumar@linux.ibm.com> wrote:
>>>>
>>>> Architectures like ppc64 provide persistent memory specific barriers
>>>> that will ensure that all stores for which the modifications are
>>>> written to persistent storage by preceding dcbfps and dcbstps
>>>> instructions have updated persistent storage before any data
>>>> access or data transfer caused by subsequent instructions is initiated.
>>>> This is in addition to the ordering done by wmb()
>>>>
>>>> Update nvdimm core such that architecture can use barriers other than
>>>> wmb to ensure all previous writes are architecturally visible for
>>>> the platform buffer flush.
>>>>
>>>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>>>> ---
>>>> drivers/md/dm-writecache.c | 2 +-
>>>> drivers/nvdimm/region_devs.c | 8 ++++----
>>>> include/linux/libnvdimm.h | 4 ++++
>>>> 3 files changed, 9 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
>>>> index 74f3c506f084..8c6b6dce64e2 100644
>>>> --- a/drivers/md/dm-writecache.c
>>>> +++ b/drivers/md/dm-writecache.c
>>>> @@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)
>>>> static void writecache_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
>>>> {
>>>> if (WC_MODE_PMEM(wc))
>>>> - wmb();
>>>> + arch_pmem_flush_barrier();
>>>> else
>>>> ssd_commit_flushed(wc, wait_for_ios);
>>>> }
>>>> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
>>>> index 4502f9c4708d..b308ad09b63d 100644
>>>> --- a/drivers/nvdimm/region_devs.c
>>>> +++ b/drivers/nvdimm/region_devs.c
>>>> @@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region *nd_region)
>>>> idx = this_cpu_add_return(flush_idx, hash_32(current->pid + idx, 8));
>>>>
>>>> /*
>>>> - * The first wmb() is needed to 'sfence' all previous writes
>>>> - * such that they are architecturally visible for the platform
>>>> - * buffer flush. Note that we've already arranged for pmem
>>>> + * The first arch_pmem_flush_barrier() is needed to 'sfence' all
>>>> + * previous writes such that they are architecturally visible for
>>>> + * the platform buffer flush. Note that we've already arranged for pmem
>>>> * writes to avoid the cache via memcpy_flushcache(). The final
>>>> * wmb() ensures ordering for the NVDIMM flush write.
>>>> */
>>>> - wmb();
>>>> + arch_pmem_flush_barrier();
>>>> for (i = 0; i < nd_region->ndr_mappings; i++)
>>>> if (ndrd_get_flush_wpq(ndrd, i, 0))
>>>> writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));
>>>> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
>>>> index 18da4059be09..66f6c65bd789 100644
>>>> --- a/include/linux/libnvdimm.h
>>>> +++ b/include/linux/libnvdimm.h
>>>> @@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void *addr, size_t size)
>>>> }
>>>> #endif
>>>>
>>>> +#ifndef arch_pmem_flush_barrier
>>>> +#define arch_pmem_flush_barrier() wmb()
>>>> +#endif
>>>
>>> I think it is out of place to define this in libnvdimm.h and it is odd
>>> to give it such a long name. The other pmem api helpers like
>>> arch_wb_cache_pmem() and arch_invalidate_pmem() are function calls for
>>> libnvdimm driver operations, this barrier is just an instruction and
>>> is closer to wmb() than the pmem api routine.
>>>
>>> Since it is a store fence for pmem, so let's just call it pmem_wmb()
>>> and define the generic version in include/linux/compiler.h. It should
>>> probably also be documented alongside dma_wmb() in
>>> Documentation/memory-barriers.txt about why code would use it over
>>> wmb(), and why a symmetric pmem_rmb() is not needed.
>>
>> How about the below? I used pmem_barrier() instead of pmem_wmb().
>
> Why? A barrier() is a bi-directional ordering mechanic for reads and
> writes, and the proposed semantics mechanism only orders writes +
> persistence. Otherwise the default fallback to wmb() on archs that
> don't override it does not make sense.
>
>> I
>> guess we wanted this to order() any data access not jus the following
>> stores to persistent storage?
>
> Why?
>
>> W.r.t why a symmetric pmem_rmb() is not
>> needed I was not sure how to explain that. Are you suggesting to explain
>> why a read/load from persistent storage don't want to wait for
>> pmem_barrier() ?
>
> I would expect that the explanation is that a typical rmb() is
> sufficient and that there is nothing pmem specific semantic for read
> ordering for pmem vs normal read-barrier semantics.
>
>>
>> modified Documentation/memory-barriers.txt
>> @@ -1935,6 +1935,16 @@ There are some more advanced barrier functions:
>> relaxed I/O accessors and the Documentation/DMA-API.txt file for more
>> information on consistent memory.
>>
>> + (*) pmem_barrier();
>> +
>> + These are for use with persistent memory to esure the ordering of stores
>> + to persistent memory region.
>
> If it was just ordering I would expect a typical wmb() to be
> sufficient, why is the pmem-specific instruction needed? I thought it
> was handshaking with hardware to ensure acceptance into a persistence
> domain *in addition* to ordering the stores.
>
>> + For example, after a non temporal write to persistent storage we use pmem_barrier()
>> + to ensures that stores have updated the persistent storage before
>> + any data access or data transfer caused by subsequent instructions is initiated.
>
> Isn't the ordering aspect is irrelevant relative to traditional wmb()?
> For example if you used the wrong sync instruction the store ordering
> will still be correct it would just not persist at the same time as
> barrier completes. Or am I misunderstanding how these new instructions
> are distinct?
>
That is correct.
-aneesh
^ permalink raw reply
* Re: [PATCH updated] libnvdimm/nvdimm/flush: Allow architecture to override the flush barrier
From: Aneesh Kumar K.V @ 2020-06-30 7:53 UTC (permalink / raw)
To: Dan Williams
Cc: Jan Kara, linux-nvdimm, Jeff Moyer, Oliver O'Halloran,
Michal Suchánek, linuxppc-dev
In-Reply-To: <03cf6d12-544f-154d-18da-a6cd204998ee@linux.ibm.com>
On 6/30/20 12:52 PM, Aneesh Kumar K.V wrote:
> On 6/30/20 12:36 PM, Dan Williams wrote:
>> On Mon, Jun 29, 2020 at 10:02 PM Aneesh Kumar K.V
>> <aneesh.kumar@linux.ibm.com> wrote:
>>>
>>> Dan Williams <dan.j.williams@intel.com> writes:
>>>
>>>> On Mon, Jun 29, 2020 at 1:29 PM Aneesh Kumar K.V
>>>> <aneesh.kumar@linux.ibm.com> wrote:
>>>>>
>>>>> Architectures like ppc64 provide persistent memory specific barriers
>>>>> that will ensure that all stores for which the modifications are
>>>>> written to persistent storage by preceding dcbfps and dcbstps
>>>>> instructions have updated persistent storage before any data
>>>>> access or data transfer caused by subsequent instructions is
>>>>> initiated.
>>>>> This is in addition to the ordering done by wmb()
>>>>>
>>>>> Update nvdimm core such that architecture can use barriers other than
>>>>> wmb to ensure all previous writes are architecturally visible for
>>>>> the platform buffer flush.
>>>>>
>>>>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>>>>> ---
>>>>> drivers/md/dm-writecache.c | 2 +-
>>>>> drivers/nvdimm/region_devs.c | 8 ++++----
>>>>> include/linux/libnvdimm.h | 4 ++++
>>>>> 3 files changed, 9 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
>>>>> index 74f3c506f084..8c6b6dce64e2 100644
>>>>> --- a/drivers/md/dm-writecache.c
>>>>> +++ b/drivers/md/dm-writecache.c
>>>>> @@ -536,7 +536,7 @@ static void ssd_commit_superblock(struct
>>>>> dm_writecache *wc)
>>>>> static void writecache_commit_flushed(struct dm_writecache *wc,
>>>>> bool wait_for_ios)
>>>>> {
>>>>> if (WC_MODE_PMEM(wc))
>>>>> - wmb();
>>>>> + arch_pmem_flush_barrier();
>>>>> else
>>>>> ssd_commit_flushed(wc, wait_for_ios);
>>>>> }
>>>>> diff --git a/drivers/nvdimm/region_devs.c
>>>>> b/drivers/nvdimm/region_devs.c
>>>>> index 4502f9c4708d..b308ad09b63d 100644
>>>>> --- a/drivers/nvdimm/region_devs.c
>>>>> +++ b/drivers/nvdimm/region_devs.c
>>>>> @@ -1206,13 +1206,13 @@ int generic_nvdimm_flush(struct nd_region
>>>>> *nd_region)
>>>>> idx = this_cpu_add_return(flush_idx, hash_32(current->pid
>>>>> + idx, 8));
>>>>>
>>>>> /*
>>>>> - * The first wmb() is needed to 'sfence' all previous writes
>>>>> - * such that they are architecturally visible for the platform
>>>>> - * buffer flush. Note that we've already arranged for pmem
>>>>> + * The first arch_pmem_flush_barrier() is needed to
>>>>> 'sfence' all
>>>>> + * previous writes such that they are architecturally
>>>>> visible for
>>>>> + * the platform buffer flush. Note that we've already
>>>>> arranged for pmem
>>>>> * writes to avoid the cache via memcpy_flushcache(). The
>>>>> final
>>>>> * wmb() ensures ordering for the NVDIMM flush write.
>>>>> */
>>>>> - wmb();
>>>>> + arch_pmem_flush_barrier();
>>>>> for (i = 0; i < nd_region->ndr_mappings; i++)
>>>>> if (ndrd_get_flush_wpq(ndrd, i, 0))
>>>>> writeq(1, ndrd_get_flush_wpq(ndrd, i, idx));
>>>>> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
>>>>> index 18da4059be09..66f6c65bd789 100644
>>>>> --- a/include/linux/libnvdimm.h
>>>>> +++ b/include/linux/libnvdimm.h
>>>>> @@ -286,4 +286,8 @@ static inline void arch_invalidate_pmem(void
>>>>> *addr, size_t size)
>>>>> }
>>>>> #endif
>>>>>
>>>>> +#ifndef arch_pmem_flush_barrier
>>>>> +#define arch_pmem_flush_barrier() wmb()
>>>>> +#endif
>>>>
>>>> I think it is out of place to define this in libnvdimm.h and it is odd
>>>> to give it such a long name. The other pmem api helpers like
>>>> arch_wb_cache_pmem() and arch_invalidate_pmem() are function calls for
>>>> libnvdimm driver operations, this barrier is just an instruction and
>>>> is closer to wmb() than the pmem api routine.
>>>>
>>>> Since it is a store fence for pmem, so let's just call it pmem_wmb()
>>>> and define the generic version in include/linux/compiler.h. It should
>>>> probably also be documented alongside dma_wmb() in
>>>> Documentation/memory-barriers.txt about why code would use it over
>>>> wmb(), and why a symmetric pmem_rmb() is not needed.
>>>
>>> How about the below? I used pmem_barrier() instead of pmem_wmb().
>>
>> Why? A barrier() is a bi-directional ordering mechanic for reads and
>> writes, and the proposed semantics mechanism only orders writes +
>> persistence. Otherwise the default fallback to wmb() on archs that
>> don't override it does not make sense.
>>
>>> I
>>> guess we wanted this to order() any data access not jus the following
>>> stores to persistent storage?
>>
>> Why?
>>
>>> W.r.t why a symmetric pmem_rmb() is not
>>> needed I was not sure how to explain that. Are you suggesting to explain
>>> why a read/load from persistent storage don't want to wait for
>>> pmem_barrier() ?
>>
>> I would expect that the explanation is that a typical rmb() is
>> sufficient and that there is nothing pmem specific semantic for read
>> ordering for pmem vs normal read-barrier semantics.
>>
Should that be rmb()? A smp_rmb() would suffice right?
-aneesh
^ permalink raw reply
* Re: [PATCH 04/11] ppc64/kexec_file: avoid stomping memory used by special regions
From: piliu @ 2020-06-30 8:13 UTC (permalink / raw)
To: Hari Bathini, Michael Ellerman, Andrew Morton
Cc: Kexec-ml, Petr Tesarik, Mahesh J Salgaonkar, Sourabh Jain, lkml,
linuxppc-dev, Mimi Zohar, Thiago Jung Bauermann, Dave Young,
Vivek Goyal, Eric Biederman
In-Reply-To: <cca6a693-a77f-885e-8ccc-967953f53800@linux.ibm.com>
On 06/30/2020 02:10 PM, Hari Bathini wrote:
>
>
> On 30/06/20 9:00 am, piliu wrote:
>>
>>
>> On 06/29/2020 01:55 PM, Hari Bathini wrote:
>>>
>>>
>>> On 28/06/20 7:44 am, piliu wrote:
>>>> Hi Hari,
>>>
>>> Hi Pingfan,
>>>
>>>>
>>>> After a quick through for this series, I have a few question/comment on
>>>> this patch for the time being. Pls see comment inline.
>>>>
>>>> On 06/27/2020 03:05 AM, Hari Bathini wrote:
>>>>> crashkernel region could have an overlap with special memory regions
>>>>> like opal, rtas, tce-table & such. These regions are referred to as
>>>>> exclude memory ranges. Setup this ranges during image probe in order
>>>>> to avoid them while finding the buffer for different kdump segments.
>>>
>>> [...]
>>>
>>>>> + /*
>>>>> + * Use the locate_mem_hole logic in kexec_add_buffer() for regular
>>>>> + * kexec_file_load syscall
>>>>> + */
>>>>> + if (kbuf->image->type != KEXEC_TYPE_CRASH)
>>>>> + return 0;
>>>> Can the ranges overlap [crashk_res.start, crashk_res.end]? Otherwise
>>>> there is no requirement for @exclude_ranges.
>>>
>>> The ranges like rtas, opal are loaded by f/w. They almost always overlap with
>>> crashkernel region. So, @exclude_ranges is required to support kdump.
>> f/w passes rtas/opal as service, then must f/w mark these ranges as
>> fdt_reserved_mem in order to make kernel aware not to use these ranges?
>
> It does. Actually, reserve_map + reserved-ranges are reserved as soon as
> memblock allocator is ready but not before crashkernel reservation.
> Check early_reserve_mem() call in kernel/prom.c
>
>> Otherwise kernel memory allocation besides kdump can also overwrite
>> these ranges.>
>> Hmm, revisiting reserve_crashkernel(). It seems not to take any reserved
>> memory into consider except kernel text. Could it work based on memblock
>> allocator?
>
> So, kdump could possibly overwrite these regions which is why an exclude
> range list is needed. Same thing was done in kexec-tools as well.
OK, got it.
Thanks,
Pingfan
>
> Thanks
> Hari
>
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
>
^ permalink raw reply
* Re: [PATCH 3/3] powerpc/pseries: Add KVM guest doorbell restrictions
From: Paul Mackerras @ 2020-06-30 8:26 UTC (permalink / raw)
To: Nicholas Piggin
Cc: kvm-ppc, Anton Blanchard, Cédric Le Goater, linuxppc-dev,
David Gibson
In-Reply-To: <1593495049.cacw882re0.astroid@bobo.none>
On Tue, Jun 30, 2020 at 03:35:08PM +1000, Nicholas Piggin wrote:
> Excerpts from Paul Mackerras's message of June 30, 2020 12:27 pm:
> > On Sun, Jun 28, 2020 at 01:04:28AM +1000, Nicholas Piggin wrote:
> >> KVM guests have certain restrictions and performance quirks when
> >> using doorbells. This patch tests for KVM environment in doorbell
> >> setup, and optimises IPI performance:
> >>
> >> - PowerVM guests may now use doorbells even if they are secure.
> >>
> >> - KVM guests no longer use doorbells if XIVE is available.
> >
> > It seems, from the fact that you completely remove
> > kvm_para_available(), that you perhaps haven't tried building with
> > CONFIG_KVM_GUEST=y.
>
> It's still there and builds:
OK, good, I missed that.
> static inline int kvm_para_available(void)
> {
> return IS_ENABLED(CONFIG_KVM_GUEST) && is_kvm_guest();
> }
>
> but...
>
> > Somewhat confusingly, that option is not used or
> > needed when building for a PAPR guest (i.e. the "pseries" platform)
> > but is used on non-IBM platforms using the "epapr" hypervisor
> > interface.
>
> ... is_kvm_guest() returns false on !PSERIES now.
And therefore kvm_para_available() returns false on all the platforms
where the code that depends on it could actually be used.
It's not correct to assume that !PSERIES means not a KVM guest.
> Not intended
> to break EPAPR. I'm not sure of a good way to share this between
> EPAPR and PSERIES, I might just make a copy of it but I'll see.
OK, so you're doing a new version?
Regards,
Paul.
^ permalink raw reply
* Re: [PATCH] crypto: af_alg - Fix regression on empty requests
From: Naresh Kamboju @ 2020-06-30 8:48 UTC (permalink / raw)
To: Herbert Xu, Eric Biggers
Cc: Sachin Sant, David S. Miller, Jarkko Sakkinen, Luis Chamberlain,
lkft-triage, open list, David Howells, Linux Next Mailing List,
linux-security-module, keyrings, Linux Crypto Mailing List,
chrubis, linux- stable, James Morris, linuxppc-dev, Jan Stancek,
LTP List, Serge E. Hallyn
In-Reply-To: <20200626062948.GA25285@gondor.apana.org.au>
On Fri, 26 Jun 2020 at 12:00, Herbert Xu <herbert@gondor.apana.org.au> wrote:
>
> On Tue, Jun 23, 2020 at 10:02:17AM -0700, Eric Biggers wrote:
> >
> > The source code for the two failing AF_ALG tests is here:
> >
> > https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/crypto/af_alg02.c
> > https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/crypto/af_alg05.c
> >
> > They use read() and write(), not send() and recv().
> >
> > af_alg02 uses read() to read from a "salsa20" request socket without writing
> > anything to it. It is expected that this returns 0, i.e. that behaves like
> > encrypting an empty message.
Since we are on this subject,
LTP af_alg02 test case fails on stable 4.9 and stable 4.4
This is not a regression because the test case has been failing from
the beginning.
Is this test case expected to fail on stable 4.9 and 4.4 ?
or any chance to fix this on these older branches ?
Test output:
af_alg02.c:52: BROK: Timed out while reading from request socket.
ref:
https://qa-reports.linaro.org/lkft/linux-stable-rc-4.9-oe/build/v4.9.228-191-g082e807235d7/testrun/2884917/suite/ltp-crypto-tests/test/af_alg02/history/
https://qa-reports.linaro.org/lkft/linux-stable-rc-4.9-oe/build/v4.9.228-191-g082e807235d7/testrun/2884606/suite/ltp-crypto-tests/test/af_alg02/log
- Naresh
^ permalink raw reply
* Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
From: Michal Suchánek @ 2020-06-30 8:54 UTC (permalink / raw)
To: Dan Williams
Cc: Jan Kara, linux-nvdimm, Aneesh Kumar K.V, Jeff Moyer,
Oliver O'Halloran, linuxppc-dev
In-Reply-To: <CAPcyv4hEV=Ps=t=3qsFq3Ob1jzf=ptoZmYTDkgr8D_G0op8uvQ@mail.gmail.com>
On Mon, Jun 29, 2020 at 06:50:15PM -0700, Dan Williams wrote:
> On Mon, Jun 29, 2020 at 1:41 PM Aneesh Kumar K.V
> <aneesh.kumar@linux.ibm.com> wrote:
> >
> > Michal Suchánek <msuchanek@suse.de> writes:
> >
> > > Hello,
> > >
> > > On Mon, Jun 29, 2020 at 07:27:20PM +0530, Aneesh Kumar K.V wrote:
> > >> nvdimm expect the flush routines to just mark the cache clean. The barrier
> > >> that mark the store globally visible is done in nvdimm_flush().
> > >>
> > >> Update the papr_scm driver to a simplified nvdim_flush callback that do
> > >> only the required barrier.
> > >>
> > >> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> > >> ---
> > >> arch/powerpc/lib/pmem.c | 6 ------
> > >> arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++
> > >> 2 files changed, 13 insertions(+), 6 deletions(-)
> > >>
> > >> diff --git a/arch/powerpc/lib/pmem.c b/arch/powerpc/lib/pmem.c
> > >> index 5a61aaeb6930..21210fa676e5 100644
> > >> --- a/arch/powerpc/lib/pmem.c
> > >> +++ b/arch/powerpc/lib/pmem.c
> > >> @@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)
> > >>
> > >> for (i = 0; i < size >> shift; i++, addr += bytes)
> > >> asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory");
> > >> -
> > >> -
> > >> - asm volatile(PPC_PHWSYNC ::: "memory");
> > >> }
> > >>
> > >> static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
> > >> @@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
> > >>
> > >> for (i = 0; i < size >> shift; i++, addr += bytes)
> > >> asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory");
> > >> -
> > >> -
> > >> - asm volatile(PPC_PHWSYNC ::: "memory");
> > >> }
> > >>
> > >> static inline void clean_pmem_range(unsigned long start, unsigned long stop)
> > >> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
> > >> index 9c569078a09f..9a9a0766f8b6 100644
> > >> --- a/arch/powerpc/platforms/pseries/papr_scm.c
> > >> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
> > >> @@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
> > >>
> > >> return 0;
> > >> }
> > >> +/*
> > >> + * We have made sure the pmem writes are done such that before calling this
> > >> + * all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here
> > >> + * we just need to add the necessary barrier to make sure the above flushes
> > >> + * are have updated persistent storage before any data access or data transfer
> > >> + * caused by subsequent instructions is initiated.
> > >> + */
> > >> +static int papr_scm_flush_sync(struct nd_region *nd_region, struct bio *bio)
> > >> +{
> > >> + arch_pmem_flush_barrier();
> > >> + return 0;
> > >> +}
> > >>
> > >> static ssize_t flags_show(struct device *dev,
> > >> struct device_attribute *attr, char *buf)
> > >> @@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
> > >> ndr_desc.mapping = &mapping;
> > >> ndr_desc.num_mappings = 1;
> > >> ndr_desc.nd_set = &p->nd_set;
> > >> + ndr_desc.flush = papr_scm_flush_sync;
> > >
> > > AFAICT currently the only device that implements flush is virtio_pmem.
> > > How does the nfit driver get away without implementing flush?
> >
> > generic_nvdimm_flush does the required barrier for nfit. The reason for
> > adding ndr_desc.flush call back for papr_scm was to avoid the usage
> > of iomem based deep flushing (ndr_region_data.flush_wpq) which is not
> > supported by papr_scm.
> >
> > BTW we do return NULL for ndrd_get_flush_wpq() on power. So the upstream
> > code also does the same thing, but in a different way.
> >
> >
> > > Also the flush takes arguments that are completely unused but a user of
> > > the pmem region must assume they are used, and call flush() on the
> > > region rather than arch_pmem_flush_barrier() directly.
> >
> > The bio argument can help a pmem driver to do range based flushing in
> > case of pmem_make_request. If bio is null then we must assume a full
> > device flush.
>
> The bio argument isn't for range based flushing, it is for flush
> operations that need to complete asynchronously.
How does the block layer determine that the pmem device needs
asynchronous fushing?
The flush() was designed for the purpose with the bio argument and only
virtio_pmem which is fulshed asynchronously used it. Now that papr_scm
resuses it fir different purpose how do you tell?
Thanks
Michal
^ permalink raw reply
* [PATCH v2] ASoC: fsl_asrc: Add an option to select internal ratio mode
From: Shengjiu Wang @ 2020-06-30 8:47 UTC (permalink / raw)
To: timur, nicoleotsuka, Xiubo.Lee, festevam, broonie, alsa-devel,
lgirdwood, perex, tiwai
Cc: linuxppc-dev, linux-kernel
The ASRC not only supports ideal ratio mode, but also supports
internal ratio mode.
For internal rato mode, the rate of clock source should be divided
with no remainder by sample rate, otherwise there is sound
distortion.
Add function fsl_asrc_select_clk() to find proper clock source for
internal ratio mode, if the clock source is available then internal
ratio mode will be selected.
With change, the ideal ratio mode is not the only option for user.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
changes in v2
- update according to Nicolin's comments
sound/soc/fsl/fsl_asrc.c | 54 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 95f6a9617b0b..4105ef2c4f99 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -582,11 +582,55 @@ static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream,
SNDRV_PCM_HW_PARAM_RATE, &fsl_asrc_rate_constraints);
}
+/**
+ * Select proper clock source for internal ratio mode
+ */
+static int fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
+ struct fsl_asrc_pair *pair,
+ int in_rate,
+ int out_rate)
+{
+ struct fsl_asrc_pair_priv *pair_priv = pair->private;
+ struct asrc_config *config = pair_priv->config;
+ int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */
+ int clk_rate, clk_index;
+ int i = 0, j = 0;
+
+ rate[0] = in_rate;
+ rate[1] = out_rate;
+
+ /* Select proper clock source for internal ratio mode */
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < ASRC_CLK_MAP_LEN; i++) {
+ clk_index = asrc_priv->clk_map[j][i];
+ clk_rate = clk_get_rate(asrc_priv->asrck_clk[clk_index]);
+ /* Only match a perfect clock source with no remainder */
+ if (clk_rate != 0 && (clk_rate / rate[j]) <= 1024 &&
+ (clk_rate % rate[j]) == 0)
+ break;
+ }
+
+ select_clk[j] = i;
+ }
+
+ /* Switch to ideal ratio mode if there is no proper clock source */
+ if (select_clk[IN] == ASRC_CLK_MAP_LEN || select_clk[OUT] == ASRC_CLK_MAP_LEN) {
+ select_clk[IN] = INCLK_NONE;
+ select_clk[OUT] = OUTCLK_ASRCK1_CLK;
+ }
+
+ config->inclk = select_clk[IN];
+ config->outclk = select_clk[OUT];
+
+ return 0;
+}
+
static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct fsl_asrc *asrc = snd_soc_dai_get_drvdata(dai);
+ struct fsl_asrc_priv *asrc_priv = asrc->private;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct fsl_asrc_pair_priv *pair_priv = pair->private;
@@ -605,8 +649,6 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.pair = pair->index;
config.channel_num = channels;
- config.inclk = INCLK_NONE;
- config.outclk = OUTCLK_ASRCK1_CLK;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_format = params_format(params);
@@ -620,6 +662,14 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.output_sample_rate = rate;
}
+ ret = fsl_asrc_select_clk(asrc_priv, pair,
+ config.input_sample_rate,
+ config.output_sample_rate);
+ if (ret) {
+ dev_err(dai->dev, "fail to select clock\n");
+ return ret;
+ }
+
ret = fsl_asrc_config_pair(pair, false);
if (ret) {
dev_err(dai->dev, "fail to config asrc pair\n");
--
2.21.0
^ permalink raw reply related
* Re: [PATCH v6 6/8] powerpc/pmem: Avoid the barrier in flush routines
From: Aneesh Kumar K.V @ 2020-06-30 9:20 UTC (permalink / raw)
To: Michal Suchánek, Dan Williams
Cc: Jan Kara, linux-nvdimm, Jeff Moyer, Oliver O'Halloran,
linuxppc-dev
In-Reply-To: <20200630085413.GW21462@kitsune.suse.cz>
On 6/30/20 2:24 PM, Michal Suchánek wrote:
> On Mon, Jun 29, 2020 at 06:50:15PM -0700, Dan Williams wrote:
>> On Mon, Jun 29, 2020 at 1:41 PM Aneesh Kumar K.V
>> <aneesh.kumar@linux.ibm.com> wrote:
>>>
>>> Michal Suchánek <msuchanek@suse.de> writes:
>>>
>>>> Hello,
>>>>
>>>> On Mon, Jun 29, 2020 at 07:27:20PM +0530, Aneesh Kumar K.V wrote:
>>>>> nvdimm expect the flush routines to just mark the cache clean. The barrier
>>>>> that mark the store globally visible is done in nvdimm_flush().
>>>>>
>>>>> Update the papr_scm driver to a simplified nvdim_flush callback that do
>>>>> only the required barrier.
>>>>>
>>>>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>>>>> ---
>>>>> arch/powerpc/lib/pmem.c | 6 ------
>>>>> arch/powerpc/platforms/pseries/papr_scm.c | 13 +++++++++++++
>>>>> 2 files changed, 13 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/arch/powerpc/lib/pmem.c b/arch/powerpc/lib/pmem.c
>>>>> index 5a61aaeb6930..21210fa676e5 100644
>>>>> --- a/arch/powerpc/lib/pmem.c
>>>>> +++ b/arch/powerpc/lib/pmem.c
>>>>> @@ -19,9 +19,6 @@ static inline void __clean_pmem_range(unsigned long start, unsigned long stop)
>>>>>
>>>>> for (i = 0; i < size >> shift; i++, addr += bytes)
>>>>> asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory");
>>>>> -
>>>>> -
>>>>> - asm volatile(PPC_PHWSYNC ::: "memory");
>>>>> }
>>>>>
>>>>> static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
>>>>> @@ -34,9 +31,6 @@ static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
>>>>>
>>>>> for (i = 0; i < size >> shift; i++, addr += bytes)
>>>>> asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory");
>>>>> -
>>>>> -
>>>>> - asm volatile(PPC_PHWSYNC ::: "memory");
>>>>> }
>>>>>
>>>>> static inline void clean_pmem_range(unsigned long start, unsigned long stop)
>>>>> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
>>>>> index 9c569078a09f..9a9a0766f8b6 100644
>>>>> --- a/arch/powerpc/platforms/pseries/papr_scm.c
>>>>> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
>>>>> @@ -630,6 +630,18 @@ static int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc,
>>>>>
>>>>> return 0;
>>>>> }
>>>>> +/*
>>>>> + * We have made sure the pmem writes are done such that before calling this
>>>>> + * all the caches are flushed/clean. We use dcbf/dcbfps to ensure this. Here
>>>>> + * we just need to add the necessary barrier to make sure the above flushes
>>>>> + * are have updated persistent storage before any data access or data transfer
>>>>> + * caused by subsequent instructions is initiated.
>>>>> + */
>>>>> +static int papr_scm_flush_sync(struct nd_region *nd_region, struct bio *bio)
>>>>> +{
>>>>> + arch_pmem_flush_barrier();
>>>>> + return 0;
>>>>> +}
>>>>>
>>>>> static ssize_t flags_show(struct device *dev,
>>>>> struct device_attribute *attr, char *buf)
>>>>> @@ -743,6 +755,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>>>>> ndr_desc.mapping = &mapping;
>>>>> ndr_desc.num_mappings = 1;
>>>>> ndr_desc.nd_set = &p->nd_set;
>>>>> + ndr_desc.flush = papr_scm_flush_sync;
>>>>
>>>> AFAICT currently the only device that implements flush is virtio_pmem.
>>>> How does the nfit driver get away without implementing flush?
>>>
>>> generic_nvdimm_flush does the required barrier for nfit. The reason for
>>> adding ndr_desc.flush call back for papr_scm was to avoid the usage
>>> of iomem based deep flushing (ndr_region_data.flush_wpq) which is not
>>> supported by papr_scm.
>>>
>>> BTW we do return NULL for ndrd_get_flush_wpq() on power. So the upstream
>>> code also does the same thing, but in a different way.
>>>
>>>
>>>> Also the flush takes arguments that are completely unused but a user of
>>>> the pmem region must assume they are used, and call flush() on the
>>>> region rather than arch_pmem_flush_barrier() directly.
>>>
>>> The bio argument can help a pmem driver to do range based flushing in
>>> case of pmem_make_request. If bio is null then we must assume a full
>>> device flush.
>>
>> The bio argument isn't for range based flushing, it is for flush
>> operations that need to complete asynchronously.
> How does the block layer determine that the pmem device needs
> asynchronous fushing?
>
set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
and dax_synchronous(dev)
> The flush() was designed for the purpose with the bio argument and only
> virtio_pmem which is fulshed asynchronously used it. Now that papr_scm
> resuses it fir different purpose how do you tell?
>
-aneesh
^ permalink raw reply
* Re: [PATCH v4 7/8] lockdep: Change hardirq{s_enabled,_context} to per-cpu variables
From: Peter Zijlstra @ 2020-06-30 9:40 UTC (permalink / raw)
To: Ahmed S. Darwish
Cc: linux-s390, linuxppc-dev, bigeasy, x86, heiko.carstens,
linux-kernel, rostedt, davem, sparclinux, linux, tglx, will,
mingo
In-Reply-To: <20200630055939.GA3676007@debian-buster-darwi.lab.linutronix.de>
On Tue, Jun 30, 2020 at 07:59:39AM +0200, Ahmed S. Darwish wrote:
> Peter Zijlstra wrote:
>
> ...
>
> > -#define lockdep_assert_irqs_disabled() do { \
> > - WARN_ONCE(debug_locks && !current->lockdep_recursion && \
> > - current->hardirqs_enabled, \
> > - "IRQs not disabled as expected\n"); \
> > - } while (0)
>
> ...
>
> > +#define lockdep_assert_irqs_disabled() \
> > +do { \
> > + WARN_ON_ONCE(debug_locks && this_cpu_read(hardirqs_enabled)); \
> > +} while (0)
>
> I think it would be nice to keep the "IRQs not disabled as expected"
> message. It makes the lockdep splat much more readable.
>
> This is similarly the case for the v3 lockdep preemption macros:
>
> https://lkml.kernel.org/r/20200630054452.3675847-5-a.darwish@linutronix.de
>
> I did not add a message though to get in-sync with the IRQ macros above.
Hurmph.. the file:line output of a splat is usually all I look at, also
__WARN_printf() generates such atrocious crap code that try and not use
it.
I suppose I should do a __WARN_str() or something, but then people are
unlikely to want to use that, too much variation etc. :/
Cursed if you do, cursed if you don't.
^ permalink raw reply
* Re: [PATCH 00/13] iommu: Remove usage of dev->archdata.iommu
From: Joerg Roedel @ 2020-06-30 10:00 UTC (permalink / raw)
To: iommu
Cc: linux-ia64, Heiko Stuebner, David Airlie, Joonas Lahtinen,
Thierry Reding, Paul Mackerras, Will Deacon, Marek Szyprowski,
x86, Russell King, Catalin Marinas, Fenghua Yu, Joerg Roedel,
intel-gfx, Jani Nikula, Rodrigo Vivi, Matthias Brugger,
linux-arm-kernel, Tony Luck, linuxppc-dev, linux-kernel,
Daniel Vetter, David Woodhouse, Lu Baolu
In-Reply-To: <20200625130836.1916-1-joro@8bytes.org>
On Thu, Jun 25, 2020 at 03:08:23PM +0200, Joerg Roedel wrote:
> Joerg Roedel (13):
> iommu/exynos: Use dev_iommu_priv_get/set()
> iommu/vt-d: Use dev_iommu_priv_get/set()
> iommu/msm: Use dev_iommu_priv_get/set()
> iommu/omap: Use dev_iommu_priv_get/set()
> iommu/rockchip: Use dev_iommu_priv_get/set()
> iommu/tegra: Use dev_iommu_priv_get/set()
> iommu/pamu: Use dev_iommu_priv_get/set()
> iommu/mediatek: Do no use dev->archdata.iommu
> x86: Remove dev->archdata.iommu pointer
> ia64: Remove dev->archdata.iommu pointer
> arm: Remove dev->archdata.iommu pointer
> arm64: Remove dev->archdata.iommu pointer
> powerpc/dma: Remove dev->archdata.iommu_domain
Applied.
^ permalink raw reply
* [PATCH v2 0/3] powerpc/pseries: IPI doorbell improvements
From: Nicholas Piggin @ 2020-06-30 11:50 UTC (permalink / raw)
To: linuxppc-dev
Cc: kvm-ppc, Nicholas Piggin, Paul Mackerras, Cédric Le Goater,
Anton Blanchard, David Gibson
Since v1:
- Fixed SMP compile error.
- Fixed EPAPR / KVM_GUEST breakage.
- Expanded patch 3 changelog a bit.
Thanks,
Nick
Nicholas Piggin (3):
powerpc: inline doorbell sending functions
powerpc/pseries: Use doorbells even if XIVE is available
powerpc/pseries: Add KVM guest doorbell restrictions
arch/powerpc/include/asm/dbell.h | 63 ++++++++++++++++++++++++++--
arch/powerpc/include/asm/firmware.h | 6 +++
arch/powerpc/include/asm/kvm_para.h | 26 ++----------
arch/powerpc/kernel/Makefile | 5 +--
arch/powerpc/kernel/dbell.c | 55 ------------------------
arch/powerpc/kernel/firmware.c | 19 +++++++++
arch/powerpc/platforms/pseries/smp.c | 62 +++++++++++++++++++--------
7 files changed, 134 insertions(+), 102 deletions(-)
--
2.23.0
^ 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