* Re: [PATCH V1 10/10] drm: Remove drm specific kmap_atomic code
From: Christoph Hellwig @ 2020-05-01 8:49 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-11-ira.weiny@intel.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V1 09/10] arch/kmap: Define kmap_atomic_prot() for all arch's
From: Christoph Hellwig @ 2020-05-01 8:48 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-10-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:44PM -0700, ira.weiny@intel.com wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> To support kmap_atomic_prot(), all architectures need to support
> protections passed to their kmap_atomic_high() function. Pass
> protections into kmap_atomic_high() and change the name to
> kmap_atomic_high_prot() to match.
>
> Then define kmap_atomic_prot() as a core function which calls
> kmap_atomic_high_prot() when needed.
>
> Finally, redefine kmap_atomic() as a wrapper of kmap_atomic_prot() with
> the default kmap_prot exported by the architectures.
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
But can you also consolidate the kmap_atomic_high_prot and
kunmap_atomic_high in linux/highmem.h instead of keeping the duplicates
in all arch headers?
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> ---
> arch/arc/include/asm/highmem.h | 2 +-
> arch/arc/mm/highmem.c | 6 +++---
> arch/arm/include/asm/highmem.h | 2 +-
> arch/arm/mm/highmem.c | 6 +++---
> arch/csky/include/asm/highmem.h | 2 +-
> arch/csky/mm/highmem.c | 6 +++---
> arch/microblaze/include/asm/highmem.h | 7 +------
> arch/microblaze/mm/highmem.c | 4 ++--
> arch/mips/include/asm/highmem.h | 2 +-
> arch/mips/mm/highmem.c | 6 +++---
> arch/nds32/include/asm/highmem.h | 2 +-
> arch/nds32/mm/highmem.c | 6 +++---
> arch/powerpc/include/asm/highmem.h | 8 +-------
> arch/powerpc/mm/highmem.c | 4 ++--
> arch/sparc/include/asm/highmem.h | 2 +-
> arch/sparc/mm/highmem.c | 6 +++---
> arch/x86/include/asm/highmem.h | 6 +-----
> arch/x86/mm/highmem_32.c | 4 ++--
> arch/xtensa/include/asm/highmem.h | 2 +-
> arch/xtensa/mm/highmem.c | 6 +++---
> include/linux/highmem.h | 5 +++--
> 21 files changed, 40 insertions(+), 54 deletions(-)
>
> diff --git a/arch/arc/include/asm/highmem.h b/arch/arc/include/asm/highmem.h
> index e16531495620..09f86bde6809 100644
> --- a/arch/arc/include/asm/highmem.h
> +++ b/arch/arc/include/asm/highmem.h
> @@ -30,7 +30,7 @@
>
> #include <asm/cacheflush.h>
>
> -extern void *kmap_atomic_high(struct page *page);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
>
> extern void kmap_init(void);
> diff --git a/arch/arc/mm/highmem.c b/arch/arc/mm/highmem.c
> index 5d3eab4ac0b0..479b0d72d3cf 100644
> --- a/arch/arc/mm/highmem.c
> +++ b/arch/arc/mm/highmem.c
> @@ -49,7 +49,7 @@
> extern pte_t * pkmap_page_table;
> static pte_t * fixmap_page_table;
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> int idx, cpu_idx;
> unsigned long vaddr;
> @@ -59,11 +59,11 @@ void *kmap_atomic_high(struct page *page)
> vaddr = FIXMAP_ADDR(idx);
>
> set_pte_at(&init_mm, vaddr, fixmap_page_table + idx,
> - mk_pte(page, kmap_prot));
> + mk_pte(page, prot));
>
> return (void *)vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kv)
> {
> diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
> index a9d5e9bce1cc..e35f2f73f6aa 100644
> --- a/arch/arm/include/asm/highmem.h
> +++ b/arch/arm/include/asm/highmem.h
> @@ -60,7 +60,7 @@ static inline void *kmap_high_get(struct page *page)
> * when CONFIG_HIGHMEM is not set.
> */
> #ifdef CONFIG_HIGHMEM
> -extern void *kmap_atomic_high(struct page *page);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
> extern void *kmap_atomic_pfn(unsigned long pfn);
> #endif
> diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
> index ac8394655a6e..e013f6b81328 100644
> --- a/arch/arm/mm/highmem.c
> +++ b/arch/arm/mm/highmem.c
> @@ -31,7 +31,7 @@ static inline pte_t get_fixmap_pte(unsigned long vaddr)
> return *ptep;
> }
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned int idx;
> unsigned long vaddr;
> @@ -67,11 +67,11 @@ void *kmap_atomic_high(struct page *page)
> * in place, so the contained TLB flush ensures the TLB is updated
> * with the new mapping.
> */
> - set_fixmap_pte(idx, mk_pte(page, kmap_prot));
> + set_fixmap_pte(idx, mk_pte(page, prot));
>
> return (void *)vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/csky/include/asm/highmem.h b/arch/csky/include/asm/highmem.h
> index 5bbbe59e60a9..59854c7ccf78 100644
> --- a/arch/csky/include/asm/highmem.h
> +++ b/arch/csky/include/asm/highmem.h
> @@ -32,7 +32,7 @@ extern pte_t *pkmap_page_table;
>
> #define ARCH_HAS_KMAP_FLUSH_TLB
> extern void kmap_flush_tlb(unsigned long addr);
> -extern void *kmap_atomic_high(struct page *page);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
> extern void *kmap_atomic_pfn(unsigned long pfn);
> extern struct page *kmap_atomic_to_page(void *ptr);
> diff --git a/arch/csky/mm/highmem.c b/arch/csky/mm/highmem.c
> index f4311669b5bb..3ae5c8cd7619 100644
> --- a/arch/csky/mm/highmem.c
> +++ b/arch/csky/mm/highmem.c
> @@ -21,7 +21,7 @@ EXPORT_SYMBOL(kmap_flush_tlb);
>
> EXPORT_SYMBOL(kmap);
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned long vaddr;
> int idx, type;
> @@ -32,12 +32,12 @@ void *kmap_atomic_high(struct page *page)
> #ifdef CONFIG_DEBUG_HIGHMEM
> BUG_ON(!pte_none(*(kmap_pte - idx)));
> #endif
> - set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
> + set_pte(kmap_pte-idx, mk_pte(page, prot));
> flush_tlb_one((unsigned long)vaddr);
>
> return (void *)vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/microblaze/include/asm/highmem.h b/arch/microblaze/include/asm/highmem.h
> index 66521fdc3a47..eb0a2cb883bd 100644
> --- a/arch/microblaze/include/asm/highmem.h
> +++ b/arch/microblaze/include/asm/highmem.h
> @@ -51,14 +51,9 @@ extern pte_t *pkmap_page_table;
> #define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
> #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
>
> -extern void *kmap_atomic_prot(struct page *page, pgprot_t prot);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
>
> -static inline void *kmap_atomic_high(struct page *page)
> -{
> - return kmap_atomic_prot(page, kmap_prot);
> -}
> -
> #define flush_cache_kmaps() { flush_icache(); flush_dcache(); }
>
> #endif /* __KERNEL__ */
> diff --git a/arch/microblaze/mm/highmem.c b/arch/microblaze/mm/highmem.c
> index 1026aeffe11a..ee8a422b2b76 100644
> --- a/arch/microblaze/mm/highmem.c
> +++ b/arch/microblaze/mm/highmem.c
> @@ -32,7 +32,7 @@
> */
> #include <asm/tlbflush.h>
>
> -void *kmap_atomic_prot(struct page *page, pgprot_t prot)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
>
> unsigned long vaddr;
> @@ -49,7 +49,7 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)
>
> return (void *) vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_prot);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
> index d9f774bd4938..c9f46b450a68 100644
> --- a/arch/mips/include/asm/highmem.h
> +++ b/arch/mips/include/asm/highmem.h
> @@ -48,7 +48,7 @@ extern pte_t *pkmap_page_table;
>
> #define ARCH_HAS_KMAP_FLUSH_TLB
> extern void kmap_flush_tlb(unsigned long addr);
> -extern void *kmap_atomic_high(struct page *page);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
> extern void *kmap_atomic_pfn(unsigned long pfn);
>
> diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
> index 87023bd1a33c..37e244cdb14e 100644
> --- a/arch/mips/mm/highmem.c
> +++ b/arch/mips/mm/highmem.c
> @@ -18,7 +18,7 @@ void kmap_flush_tlb(unsigned long addr)
> }
> EXPORT_SYMBOL(kmap_flush_tlb);
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned long vaddr;
> int idx, type;
> @@ -29,12 +29,12 @@ void *kmap_atomic_high(struct page *page)
> #ifdef CONFIG_DEBUG_HIGHMEM
> BUG_ON(!pte_none(*(kmap_pte - idx)));
> #endif
> - set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
> + set_pte(kmap_pte-idx, mk_pte(page, prot));
> local_flush_tlb_one((unsigned long)vaddr);
>
> return (void*) vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/nds32/include/asm/highmem.h b/arch/nds32/include/asm/highmem.h
> index 97648b678108..1f9fc74d112d 100644
> --- a/arch/nds32/include/asm/highmem.h
> +++ b/arch/nds32/include/asm/highmem.h
> @@ -51,7 +51,7 @@ extern void kmap_init(void);
> * when CONFIG_HIGHMEM is not set.
> */
> #ifdef CONFIG_HIGHMEM
> -extern void *kmap_atomic_high(struct page *page);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
> extern void *kmap_atomic_pfn(unsigned long pfn);
> extern struct page *kmap_atomic_to_page(void *ptr);
> diff --git a/arch/nds32/mm/highmem.c b/arch/nds32/mm/highmem.c
> index 809f8c830f06..63ded527c1e8 100644
> --- a/arch/nds32/mm/highmem.c
> +++ b/arch/nds32/mm/highmem.c
> @@ -10,7 +10,7 @@
> #include <asm/fixmap.h>
> #include <asm/tlbflush.h>
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned int idx;
> unsigned long vaddr, pte;
> @@ -21,7 +21,7 @@ void *kmap_atomic_high(struct page *page)
>
> idx = type + KM_TYPE_NR * smp_processor_id();
> vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
> - pte = (page_to_pfn(page) << PAGE_SHIFT) | (kmap_prot);
> + pte = (page_to_pfn(page) << PAGE_SHIFT) | prot;
> ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr);
> set_pte(ptep, pte);
>
> @@ -32,7 +32,7 @@ void *kmap_atomic_high(struct page *page)
> return (void *)vaddr;
> }
>
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h
> index d264aebcaa9b..edd01bbe5a44 100644
> --- a/arch/powerpc/include/asm/highmem.h
> +++ b/arch/powerpc/include/asm/highmem.h
> @@ -59,15 +59,9 @@ extern pte_t *pkmap_page_table;
> #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
> #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
>
> -extern void *kmap_atomic_prot(struct page *page, pgprot_t prot);
> +extern void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> extern void kunmap_atomic_high(void *kvaddr);
>
> -static inline void *kmap_atomic_high(struct page *page)
> -{
> - return kmap_atomic_prot(page, kmap_prot);
> -}
> -
> -
> #define flush_cache_kmaps() flush_cache_all()
>
> #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/mm/highmem.c b/arch/powerpc/mm/highmem.c
> index 162958321e28..35071c2913f1 100644
> --- a/arch/powerpc/mm/highmem.c
> +++ b/arch/powerpc/mm/highmem.c
> @@ -24,7 +24,7 @@
> #include <linux/highmem.h>
> #include <linux/module.h>
>
> -void *kmap_atomic_prot(struct page *page, pgprot_t prot)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned long vaddr;
> int idx, type;
> @@ -38,7 +38,7 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)
>
> return (void*) vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_prot);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h
> index 94dd6e4c5fa4..d5c5700672de 100644
> --- a/arch/sparc/include/asm/highmem.h
> +++ b/arch/sparc/include/asm/highmem.h
> @@ -50,7 +50,7 @@ void kmap_init(void) __init;
>
> #define PKMAP_END (PKMAP_ADDR(LAST_PKMAP))
>
> -void *kmap_atomic_high(struct page *page);
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> void kunmap_atomic_high(void *kvaddr);
>
> #define flush_cache_kmaps() flush_cache_all()
> diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
> index 9f06d75e88e1..414f578d1e57 100644
> --- a/arch/sparc/mm/highmem.c
> +++ b/arch/sparc/mm/highmem.c
> @@ -54,7 +54,7 @@ void __init kmap_init(void)
> kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);
> }
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned long vaddr;
> long idx, type;
> @@ -73,7 +73,7 @@ void *kmap_atomic_high(struct page *page)
> #ifdef CONFIG_DEBUG_HIGHMEM
> BUG_ON(!pte_none(*(kmap_pte-idx)));
> #endif
> - set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
> + set_pte(kmap_pte-idx, mk_pte(page, prot));
> /* XXX Fix - Anton */
> #if 0
> __flush_tlb_one(vaddr);
> @@ -83,7 +83,7 @@ void *kmap_atomic_high(struct page *page)
>
> return (void*) vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h
> index ff87aba96eee..009b8e22e906 100644
> --- a/arch/x86/include/asm/highmem.h
> +++ b/arch/x86/include/asm/highmem.h
> @@ -58,11 +58,7 @@ extern unsigned long highstart_pfn, highend_pfn;
> #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
> #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
>
> -extern void *kmap_atomic_prot(struct page *page, pgprot_t prot);
> -void *kmap_atomic_high(struct page *page)
> -{
> - return kmap_atomic_prot(page, kmap_prot);
> -}
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> void kunmap_atomic_high(void *kvaddr);
> void *kmap_atomic_pfn(unsigned long pfn);
> void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
> diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
> index af07a6842743..075fe51317b0 100644
> --- a/arch/x86/mm/highmem_32.c
> +++ b/arch/x86/mm/highmem_32.c
> @@ -4,7 +4,7 @@
> #include <linux/swap.h> /* for totalram_pages */
> #include <linux/memblock.h>
>
> -void *kmap_atomic_prot(struct page *page, pgprot_t prot)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> unsigned long vaddr;
> int idx, type;
> @@ -18,7 +18,7 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)
>
> return (void *)vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_prot);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> /*
> * This is the same as kmap_atomic() but can map memory that doesn't
> diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h
> index a60a02dc68f6..7152aeb1e3a4 100644
> --- a/arch/xtensa/include/asm/highmem.h
> +++ b/arch/xtensa/include/asm/highmem.h
> @@ -68,7 +68,7 @@ static inline void flush_cache_kmaps(void)
> flush_cache_all();
> }
>
> -void *kmap_atomic_high(struct page *page);
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot);
> void kunmap_atomic_high(void *kvaddr);
>
> void kmap_init(void);
> diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c
> index 8c58c4c37033..fe56644d7b23 100644
> --- a/arch/xtensa/mm/highmem.c
> +++ b/arch/xtensa/mm/highmem.c
> @@ -37,7 +37,7 @@ static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
> color;
> }
>
> -void *kmap_atomic_high(struct page *page)
> +void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
> {
> enum fixed_addresses idx;
> unsigned long vaddr;
> @@ -48,11 +48,11 @@ void *kmap_atomic_high(struct page *page)
> #ifdef CONFIG_DEBUG_HIGHMEM
> BUG_ON(!pte_none(*(kmap_pte + idx)));
> #endif
> - set_pte(kmap_pte + idx, mk_pte(page, kmap_prot));
> + set_pte(kmap_pte + idx, mk_pte(page, prot));
>
> return (void *)vaddr;
> }
> -EXPORT_SYMBOL(kmap_atomic_high);
> +EXPORT_SYMBOL(kmap_atomic_high_prot);
>
> void kunmap_atomic_high(void *kvaddr)
> {
> diff --git a/include/linux/highmem.h b/include/linux/highmem.h
> index 601df07607a4..b10e8a39ae60 100644
> --- a/include/linux/highmem.h
> +++ b/include/linux/highmem.h
> @@ -74,14 +74,15 @@ static inline void kunmap(struct page *page)
> * be used in IRQ contexts, so in some (very limited) cases we need
> * it.
> */
> -static inline void *kmap_atomic(struct page *page)
> +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
> {
> preempt_disable();
> pagefault_disable();
> if (!PageHighMem(page))
> return page_address(page);
> - return kmap_atomic_high(page);
> + return kmap_atomic_high_prot(page, prot);
> }
> +#define kmap_atomic(page) kmap_atomic_prot(page, kmap_prot)
>
> /* declarations for linux/mm/highmem.c */
> unsigned int nr_free_highpages(void);
> --
> 2.25.1
>
---end quoted text---
^ permalink raw reply
* Re: [PATCH V1 08/10] arch/kmap: Don't hard code kmap_prot values
From: Christoph Hellwig @ 2020-05-01 8:47 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-9-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:43PM -0700, ira.weiny@intel.com wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> To support kmap_atomic_prot() on all architectures each arch must
> support protections passed in to them.
>
> Change csky, mips, nds32 and xtensa to use their global kmap_prot value
> rather than a hard coded value which was equal.
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* sparc-related comment, to Re: [PATCH V1 07/10] arch/kmap: Ensure kmap_prot visibility
From: Christoph Hellwig @ 2020-05-01 8:44 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-8-ira.weiny@intel.com>
> --- a/arch/sparc/mm/highmem.c
> +++ b/arch/sparc/mm/highmem.c
> @@ -33,6 +33,7 @@
> #include <asm/vaddrs.h>
>
> pgprot_t kmap_prot;
> +EXPORT_SYMBOL(kmap_prot);
Btw, I don't see why sparc needs this as a variable, as there is just
a single assignment to it.
If sparc is sorted out we can always make it a define, and use a define
for kmap_prot that defaults to PAGE_KERNEL, avoiding a little
more duplication.
^ permalink raw reply
* Re: [PATCH V1 06/10] arch/kunmap_atomic: Consolidate duplicate code
From: Christoph Hellwig @ 2020-05-01 8:39 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-7-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:41PM -0700, ira.weiny@intel.com wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> Every single architecture (including !CONFIG_HIGHMEM) calls...
>
> pagefault_enable();
> preempt_enable();
>
> ... before returning from __kunmap_atomic(). Lift this code into the
> kunmap_atomic() macro.
>
> While we are at it rename __kunmap_atomic() to kunmap_atomic_high() to
> be consistent.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V1 05/10] arch/kmap_atomic: Consolidate duplicate code
From: Christoph Hellwig @ 2020-05-01 8:39 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-6-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:40PM -0700, ira.weiny@intel.com wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> Every arch has the same code to ensure atomic operations and a check for
> !HIGHMEM page.
>
> Remove the duplicate code by defining a core kmap_atomic() which only
> calls the arch specific kmap_atomic_high() when the page is high memory.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V1 04/10] arch/kunmap: Remove duplicate kunmap implementations
From: Christoph Hellwig @ 2020-05-01 8:38 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-5-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:39PM -0700, ira.weiny@intel.com wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> All architectures do exactly the same thing for kunmap(); remove all the
> duplicate definitions and lift the call to the core.
>
> This also has the benefit of changing kmap_unmap() on a number of
> architectures to be an inline call rather than an actual function.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V1 03/10] arch/kmap: Remove redundant arch specific kmaps
From: Christoph Hellwig @ 2020-05-01 8:37 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-4-ira.weiny@intel.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V1 02/10] arch/xtensa: Move kmap build bug out of the way
From: Christoph Hellwig @ 2020-05-01 8:36 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-3-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:37PM -0700, ira.weiny@intel.com wrote:
> @@ -88,6 +88,11 @@ void __init kmap_init(void)
> {
> unsigned long kmap_vstart;
>
> + /* Check if this memory layout is broken because PKMAP overlaps
> + * page table.
> + */
> + BUILD_BUG_ON(PKMAP_BASE <
> + TLBTEMP_BASE_1 + TLBTEMP_SIZE);
This can fit on a single line. Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH V1 01/10] arch/kmap: Remove BUG_ON()
From: Christoph Hellwig @ 2020-05-01 8:35 UTC (permalink / raw)
To: ira.weiny
Cc: Peter Zijlstra, Dave Hansen, dri-devel, linux-mips,
James E.J. Bottomley, Max Filippov, Huang Rui, Paul Mackerras,
H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
linux-csky, Ingo Molnar, linux-snps-arc, linux-xtensa,
Borislav Petkov, Andy Lutomirski, Thomas Gleixner,
linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer, linux-parisc,
linux-kernel, David S. Miller, Andrew Morton, linuxppc-dev,
Christian Koenig
In-Reply-To: <20200430203845.582900-2-ira.weiny@intel.com>
On Thu, Apr 30, 2020 at 01:38:36PM -0700, ira.weiny@intel.com wrote:
> From: Ira Weiny <ira.weiny@intel.com>
>
> Replace the use of BUG_ON(in_interrupt()) in the kmap() and kunmap()
> in favor of might_sleep().
>
> Besides the benefits of might_sleep(), this normalizes the
> implementations such that they can be made generic in subsequent
> patches.
>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* [PATCH 1/3] ASoC: fsl_esai: introduce SoC specific data
From: Shengjiu Wang @ 2020-05-01 8:12 UTC (permalink / raw)
To: timur, nicoleotsuka, Xiubo.Lee, festevam, broonie, perex, tiwai,
alsa-devel, lgirdwood, robh+dt, devicetree
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1588320655.git.shengjiu.wang@nxp.com>
Introduce a SoC specific data structure which contains the
differences between the different SoCs.
This makes it easier to support more differences without having
to introduce a new if/else each time.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl_esai.c | 46 ++++++++++++++++++++++++++++++++--------
1 file changed, 37 insertions(+), 9 deletions(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 84290be778f0..bac65ba7fbad 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -21,6 +21,17 @@
SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
+/**
+ * fsl_esai_soc_data: soc specific data
+ *
+ * @imx: for imx platform
+ * @reset_at_xrun: flags for enable reset operaton
+ */
+struct fsl_esai_soc_data {
+ bool imx;
+ bool reset_at_xrun;
+};
+
/**
* fsl_esai: ESAI private data
*
@@ -33,6 +44,7 @@
* @fsysclk: system clock source to derive HCK, SCK and FS
* @spbaclk: SPBA clock (optional, depending on SoC design)
* @task: tasklet to handle the reset operation
+ * @soc: soc specific data
* @lock: spin lock between hw_reset() and trigger()
* @fifo_depth: depth of tx/rx FIFO
* @slot_width: width of each DAI slot
@@ -44,7 +56,6 @@
* @sck_div: if using PSR/PM dividers for SCKx clock
* @slave_mode: if fully using DAI slave mode
* @synchronous: if using tx/rx synchronous mode
- * @reset_at_xrun: flags for enable reset operaton
* @name: driver name
*/
struct fsl_esai {
@@ -57,6 +68,7 @@ struct fsl_esai {
struct clk *fsysclk;
struct clk *spbaclk;
struct tasklet_struct task;
+ const struct fsl_esai_soc_data *soc;
spinlock_t lock; /* Protect hw_reset and trigger */
u32 fifo_depth;
u32 slot_width;
@@ -70,10 +82,24 @@ struct fsl_esai {
bool sck_div[2];
bool slave_mode;
bool synchronous;
- bool reset_at_xrun;
char name[32];
};
+static struct fsl_esai_soc_data fsl_esai_vf610 = {
+ .imx = false,
+ .reset_at_xrun = true,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx35 = {
+ .imx = true,
+ .reset_at_xrun = true,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx6ull = {
+ .imx = true,
+ .reset_at_xrun = false,
+};
+
static irqreturn_t esai_isr(int irq, void *devid)
{
struct fsl_esai *esai_priv = (struct fsl_esai *)devid;
@@ -85,7 +111,7 @@ static irqreturn_t esai_isr(int irq, void *devid)
regmap_read(esai_priv->regmap, REG_ESAI_SAISR, &saisr);
if ((saisr & (ESAI_SAISR_TUE | ESAI_SAISR_ROE)) &&
- esai_priv->reset_at_xrun) {
+ esai_priv->soc->reset_at_xrun) {
dev_dbg(&pdev->dev, "reset module for xrun\n");
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
ESAI_xCR_xEIE_MASK, 0);
@@ -936,9 +962,11 @@ static int fsl_esai_probe(struct platform_device *pdev)
esai_priv->pdev = pdev;
snprintf(esai_priv->name, sizeof(esai_priv->name), "%pOFn", np);
- if (of_device_is_compatible(np, "fsl,vf610-esai") ||
- of_device_is_compatible(np, "fsl,imx35-esai"))
- esai_priv->reset_at_xrun = true;
+ esai_priv->soc = of_device_get_match_data(&pdev->dev);
+ if (!esai_priv->soc) {
+ dev_err(&pdev->dev, "failed to get soc data\n");
+ return -ENODEV;
+ }
/* Get the addresses and IRQ */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1063,9 +1091,9 @@ static int fsl_esai_remove(struct platform_device *pdev)
}
static const struct of_device_id fsl_esai_dt_ids[] = {
- { .compatible = "fsl,imx35-esai", },
- { .compatible = "fsl,vf610-esai", },
- { .compatible = "fsl,imx6ull-esai", },
+ { .compatible = "fsl,imx35-esai", .data = &fsl_esai_imx35 },
+ { .compatible = "fsl,vf610-esai", .data = &fsl_esai_vf610 },
+ { .compatible = "fsl,imx6ull-esai", .data = &fsl_esai_imx6ull },
{}
};
MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
--
2.21.0
^ permalink raw reply related
* [PATCH 2/3] ASoC: fsl_esai: Add support for imx8qm
From: Shengjiu Wang @ 2020-05-01 8:12 UTC (permalink / raw)
To: timur, nicoleotsuka, Xiubo.Lee, festevam, broonie, perex, tiwai,
alsa-devel, lgirdwood, robh+dt, devicetree
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1588320655.git.shengjiu.wang@nxp.com>
The difference for esai on imx8qm is that DMA device is EDMA.
EDMA requires the period size to be multiple of maxburst. Otherwise
the remaining bytes are not transferred and thus noise is produced.
We can handle this issue by adding a constraint on
SNDRV_PCM_HW_PARAM_PERIOD_SIZE to be multiple of tx/rx maxburst value.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
sound/soc/fsl/fsl_esai.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index bac65ba7fbad..61b5c0bde788 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -26,10 +26,12 @@
*
* @imx: for imx platform
* @reset_at_xrun: flags for enable reset operaton
+ * @use_edma: edma is used.
*/
struct fsl_esai_soc_data {
bool imx;
bool reset_at_xrun;
+ bool use_edma;
};
/**
@@ -88,16 +90,25 @@ struct fsl_esai {
static struct fsl_esai_soc_data fsl_esai_vf610 = {
.imx = false,
.reset_at_xrun = true,
+ .use_edma = false,
};
static struct fsl_esai_soc_data fsl_esai_imx35 = {
.imx = true,
.reset_at_xrun = true,
+ .use_edma = false,
};
static struct fsl_esai_soc_data fsl_esai_imx6ull = {
.imx = true,
.reset_at_xrun = false,
+ .use_edma = false,
+};
+
+static struct fsl_esai_soc_data fsl_esai_imx8qm = {
+ .imx = true,
+ .reset_at_xrun = false,
+ .use_edma = true,
};
static irqreturn_t esai_isr(int irq, void *devid)
@@ -513,6 +524,7 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
if (!dai->active) {
/* Set synchronous mode */
@@ -527,6 +539,12 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2));
}
+ if (esai_priv->soc->use_edma)
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ tx ? esai_priv->dma_params_tx.maxburst :
+ esai_priv->dma_params_rx.maxburst);
+
return 0;
}
@@ -1094,6 +1112,7 @@ static const struct of_device_id fsl_esai_dt_ids[] = {
{ .compatible = "fsl,imx35-esai", .data = &fsl_esai_imx35 },
{ .compatible = "fsl,vf610-esai", .data = &fsl_esai_vf610 },
{ .compatible = "fsl,imx6ull-esai", .data = &fsl_esai_imx6ull },
+ { .compatible = "fsl,imx8qm-esai", .data = &fsl_esai_imx8qm },
{}
};
MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids);
--
2.21.0
^ permalink raw reply related
* [PATCH 3/3] ASoC: fsl_esai: Add new compatible string for imx8qm
From: Shengjiu Wang @ 2020-05-01 8:12 UTC (permalink / raw)
To: timur, nicoleotsuka, Xiubo.Lee, festevam, broonie, perex, tiwai,
alsa-devel, lgirdwood, robh+dt, devicetree
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1588320655.git.shengjiu.wang@nxp.com>
Add new compatible string "fsl,imx8qm-esai" in the binding document.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
Documentation/devicetree/bindings/sound/fsl,esai.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt
index 0e6e2166f76c..0a2480aeecf0 100644
--- a/Documentation/devicetree/bindings/sound/fsl,esai.txt
+++ b/Documentation/devicetree/bindings/sound/fsl,esai.txt
@@ -12,6 +12,7 @@ Required properties:
"fsl,imx35-esai",
"fsl,vf610-esai",
"fsl,imx6ull-esai",
+ "fsl,imx8qm-esai",
- reg : Offset and length of the register set for the device.
--
2.21.0
^ permalink raw reply related
* [PATCH 0/3] ASoC: fsl_esai: Add support for imx8qm
From: Shengjiu Wang @ 2020-05-01 8:12 UTC (permalink / raw)
To: timur, nicoleotsuka, Xiubo.Lee, festevam, broonie, perex, tiwai,
alsa-devel, lgirdwood, robh+dt, devicetree
Cc: linuxppc-dev, linux-kernel
Add support for imx8qm.
Shengjiu Wang (3):
ASoC: fsl_esai: introduce SoC specific data
ASoC: fsl_esai: Add support for imx8qm
ASoC: fsl_esai: Add new compatible string for imx8qm
.../devicetree/bindings/sound/fsl,esai.txt | 1 +
sound/soc/fsl/fsl_esai.c | 65 ++++++++++++++++---
2 files changed, 57 insertions(+), 9 deletions(-)
--
2.21.0
^ permalink raw reply
* Re: [PATCH V1 10/10] drm: Remove drm specific kmap_atomic code
From: Christian König @ 2020-05-01 7:23 UTC (permalink / raw)
To: ira.weiny, linux-kernel, Andrew Morton, Huang Rui
Cc: Peter Zijlstra, Dave Hansen, dri-devel, James E.J. Bottomley,
Max Filippov, Paul Mackerras, H. Peter Anvin, sparclinux,
Thomas Gleixner, Helge Deller, x86, linux-csky, Ingo Molnar,
linux-snps-arc, linux-xtensa, Borislav Petkov, Andy Lutomirski,
Dan Williams, linux-arm-kernel, Chris Zankel, Thomas Bogendoerfer,
linux-parisc, linux-mips, linuxppc-dev, David S. Miller
In-Reply-To: <20200430203845.582900-11-ira.weiny@intel.com>
Am 30.04.20 um 22:38 schrieb ira.weiny@intel.com:
> From: Ira Weiny <ira.weiny@intel.com>
>
> kmap_atomic_prot() is now exported by all architectures. Use this
> function rather than open coding a driver specific kmap_atomic.
>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Ah, yes looking into this once more this was on my TODO list for quite a
while as well.
Patch is Reviewed-by: Christian König <christian.koenig@amd.com>, feel
free to push it upstream through whatever channel you like or ping me if
I should pick it up into drm-misc-next.
Regards,
Christian.
> ---
> drivers/gpu/drm/ttm/ttm_bo_util.c | 56 ++--------------------------
> drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 16 ++++----
> include/drm/ttm/ttm_bo_api.h | 4 --
> 3 files changed, 12 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
> index 52d2b71f1588..f09b096ba4fd 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
> @@ -257,54 +257,6 @@ static int ttm_copy_io_page(void *dst, void *src, unsigned long page)
> return 0;
> }
>
> -#ifdef CONFIG_X86
> -#define __ttm_kmap_atomic_prot(__page, __prot) kmap_atomic_prot(__page, __prot)
> -#define __ttm_kunmap_atomic(__addr) kunmap_atomic(__addr)
> -#else
> -#define __ttm_kmap_atomic_prot(__page, __prot) vmap(&__page, 1, 0, __prot)
> -#define __ttm_kunmap_atomic(__addr) vunmap(__addr)
> -#endif
> -
> -
> -/**
> - * ttm_kmap_atomic_prot - Efficient kernel map of a single page with
> - * specified page protection.
> - *
> - * @page: The page to map.
> - * @prot: The page protection.
> - *
> - * This function maps a TTM page using the kmap_atomic api if available,
> - * otherwise falls back to vmap. The user must make sure that the
> - * specified page does not have an aliased mapping with a different caching
> - * policy unless the architecture explicitly allows it. Also mapping and
> - * unmapping using this api must be correctly nested. Unmapping should
> - * occur in the reverse order of mapping.
> - */
> -void *ttm_kmap_atomic_prot(struct page *page, pgprot_t prot)
> -{
> - if (pgprot_val(prot) == pgprot_val(PAGE_KERNEL))
> - return kmap_atomic(page);
> - else
> - return __ttm_kmap_atomic_prot(page, prot);
> -}
> -EXPORT_SYMBOL(ttm_kmap_atomic_prot);
> -
> -/**
> - * ttm_kunmap_atomic_prot - Unmap a page that was mapped using
> - * ttm_kmap_atomic_prot.
> - *
> - * @addr: The virtual address from the map.
> - * @prot: The page protection.
> - */
> -void ttm_kunmap_atomic_prot(void *addr, pgprot_t prot)
> -{
> - if (pgprot_val(prot) == pgprot_val(PAGE_KERNEL))
> - kunmap_atomic(addr);
> - else
> - __ttm_kunmap_atomic(addr);
> -}
> -EXPORT_SYMBOL(ttm_kunmap_atomic_prot);
> -
> static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
> unsigned long page,
> pgprot_t prot)
> @@ -316,13 +268,13 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
> return -ENOMEM;
>
> src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
> - dst = ttm_kmap_atomic_prot(d, prot);
> + dst = kmap_atomic_prot(d, prot);
> if (!dst)
> return -ENOMEM;
>
> memcpy_fromio(dst, src, PAGE_SIZE);
>
> - ttm_kunmap_atomic_prot(dst, prot);
> + kunmap_atomic(dst);
>
> return 0;
> }
> @@ -338,13 +290,13 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
> return -ENOMEM;
>
> dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
> - src = ttm_kmap_atomic_prot(s, prot);
> + src = kmap_atomic_prot(s, prot);
> if (!src)
> return -ENOMEM;
>
> memcpy_toio(dst, src, PAGE_SIZE);
>
> - ttm_kunmap_atomic_prot(src, prot);
> + kunmap_atomic(src);
>
> return 0;
> }
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> index bb46ca0c458f..94d456a1d1a9 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
> @@ -374,12 +374,12 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
> copy_size = min_t(u32, copy_size, PAGE_SIZE - src_page_offset);
>
> if (unmap_src) {
> - ttm_kunmap_atomic_prot(d->src_addr, d->src_prot);
> + kunmap_atomic(d->src_addr);
> d->src_addr = NULL;
> }
>
> if (unmap_dst) {
> - ttm_kunmap_atomic_prot(d->dst_addr, d->dst_prot);
> + kunmap_atomic(d->dst_addr);
> d->dst_addr = NULL;
> }
>
> @@ -388,8 +388,8 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
> return -EINVAL;
>
> d->dst_addr =
> - ttm_kmap_atomic_prot(d->dst_pages[dst_page],
> - d->dst_prot);
> + kmap_atomic_prot(d->dst_pages[dst_page],
> + d->dst_prot);
> if (!d->dst_addr)
> return -ENOMEM;
>
> @@ -401,8 +401,8 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
> return -EINVAL;
>
> d->src_addr =
> - ttm_kmap_atomic_prot(d->src_pages[src_page],
> - d->src_prot);
> + kmap_atomic_prot(d->src_pages[src_page],
> + d->src_prot);
> if (!d->src_addr)
> return -ENOMEM;
>
> @@ -499,9 +499,9 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
> }
> out:
> if (d.src_addr)
> - ttm_kunmap_atomic_prot(d.src_addr, d.src_prot);
> + kunmap_atomic(d.src_addr);
> if (d.dst_addr)
> - ttm_kunmap_atomic_prot(d.dst_addr, d.dst_prot);
> + kunmap_atomic(d.dst_addr);
>
> return ret;
> }
> diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
> index 0a9d042e075a..de1ccdcd5703 100644
> --- a/include/drm/ttm/ttm_bo_api.h
> +++ b/include/drm/ttm/ttm_bo_api.h
> @@ -668,10 +668,6 @@ int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo);
> int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
> struct ttm_bo_device *bdev);
>
> -void *ttm_kmap_atomic_prot(struct page *page, pgprot_t prot);
> -
> -void ttm_kunmap_atomic_prot(void *addr, pgprot_t prot);
> -
> /**
> * ttm_bo_io
> *
^ permalink raw reply
* Re: [PATCH v5 0/5] Track and expose idle PURR and SPURR ticks
From: Gautham R Shenoy @ 2020-05-01 5:50 UTC (permalink / raw)
To: Gautham R Shenoy
Cc: Nathan Lynch, Tyrel Datwyler, linux-kernel, Kamalesh Babulal,
Naveen N. Rao, Vaidyanathan Srinivasan, linuxppc-dev
In-Reply-To: <20200430041612.GA25522@in.ibm.com>
On Thu, Apr 30, 2020 at 09:46:13AM +0530, Gautham R Shenoy wrote:
> Hello Michael,
> > >
> > > Michael, could you please consider this for 5.8 ?
> >
> > Yes. Has it been tested on KVM at all?
>
> No. I haven't tested this on KVM. Will do that today.
The results on Shared LPAR and KVM are as follows:
---------------------------------------------------
The lparstat results on a Shared LPAR are consistent with that
observed on a dedicated LPAR when at least one of the threads of the
core is active. When all the threads are idle, the lparstat shows
incorrect idle percentage. But this is perhaps due to the fact that
the Hypervisor puts a completely idle core in some power-saving state
with runlatch turned off due to which PURR counts on the threads of a
core do not add up to the elapsed timebase ticks. The results are in
section A) below.
lparstat is not supported on KVM. However, I performed some basic
sanity checks on purr, spurr, idle_purr, and idle_spurr sysfs files
that show up after this patch series. When CPUs are offlined, the
idle_purr and idle_spurr sysfs files no longer show up, just like purr
and spurr sysfs files. The values of the counters monotonically
increase, except when the CPU is busy, in which case the idle_purr and
idle_spurr counts are stagnant as expected.
However, I don't think the even the values of PURR or SPURR make much
sense on KVM guest, since the Linux Hypervisor doesn't set additional
registers such as RWMR, except on POWER8, where the KVM sets RWMR
corresponding to the number of online threads in a vCORE before
dispatching the vcore. I haven't been able to test it on a POWER8
guest yet. The results on POWER9 are in section B) below.
A ) Shared LPAR
======================
1. When all the threads of the core are running a CPU-Hog
# ./lparstat -E 1 5
System Configuration
type=Shared mode=Capped smt=8 lcpu=6 mem=10362752 kB cpus=10 ent=6.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
100.00 0.00 2.90GHz[126%] 126.00 0.00
100.00 0.00 2.90GHz[126%] 126.00 0.00
100.00 0.00 2.90GHz[126%] 126.00 0.00
100.00 0.00 2.90GHz[126%] 126.00 0.00
100.01 0.00 2.90GHz[126%] 126.01 0.00
2. When 4 threads of a core are running CPU Hogs, with the remaining 4
threads idle.
# ./lparstat -E 1 5
System Configuration
type=Shared mode=Capped smt=8 lcpu=6 mem=10362752 kB cpus=10 ent=6.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
81.06 18.94 2.97GHz[129%] 104.56 24.44
81.05 18.95 2.97GHz[129%] 104.56 24.44
81.06 18.95 2.97GHz[129%] 104.56 24.44
81.06 18.95 2.97GHz[129%] 104.56 24.44
81.05 18.95 2.97GHz[129%] 104.56 24.45
3. When 2 threads of a core are running CPU Hogs, with the other 6
threads idle.
# ./lparstat -E 1 5
System Configuration
type=Shared mode=Capped smt=8 lcpu=6 mem=10362752 kB cpus=10 ent=6.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
65.21 34.79 3.13GHz[136%] 88.69 47.31
65.20 34.81 3.13GHz[136%] 88.67 47.33
64.25 35.76 3.13GHz[136%] 87.38 48.63
63.68 36.31 3.13GHz[136%] 86.60 49.39
63.55 36.45 3.13GHz[136%] 86.42 49.58
4. When a single thread of the core is running CPU Hog, remaining 7
threads are idle.
# ./lparstat -E 1 5
System Configuration
type=Shared mode=Capped smt=8 lcpu=6 mem=10362752 kB cpus=10 ent=6.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
31.80 68.20 3.20GHz[139%] 44.20 94.80
31.80 68.20 3.20GHz[139%] 44.20 94.81
31.80 68.20 3.20GHz[139%] 44.20 94.80
31.80 68.21 3.20GHz[139%] 44.20 94.81
31.79 68.21 3.20GHz[139%] 44.19 94.81
5. When the LPAR is idle:
# ./lparstat -E 1 5
System Configuration
type=Shared mode=Capped smt=8 lcpu=6 mem=10362752 kB cpus=10 ent=6.00
---Actual--- -Normalized-
%busy %idle Frequency %busy %idle
------ ------ ------------- ------ ------
0.04 0.14 2.41GHz[105%] 0.04 0.15
0.04 0.15 2.36GHz[102%] 0.04 0.15
0.03 0.13 2.35GHz[102%] 0.03 0.14
0.03 0.13 2.31GHz[100%] 0.03 0.13
0.03 0.13 2.32GHz[101%] 0.03 0.14
In this case, the sum of the PURR values do not add up to the elapsed
TB. This is probably due to the Hypervisor putting the core into some
power-saving state with the runlatch turned off.
# ./purr_tb -t 8
Got threads_per_core = 8
CORE 0:
CPU 0 : Delta PURR : 85744
CPU 1 : Delta PURR : 113632
CPU 2 : Delta PURR : 78224
CPU 3 : Delta PURR : 68856
CPU 4 : Delta PURR : 78064
CPU 5 : Delta PURR : 60488
CPU 6 : Delta PURR : 77776
CPU 7 : Delta PURR : 59464
Total Delta PURR : 622248 (Expected ~513156096)
B) KVM guest
==============================
vCPU idle:
-------------
Sampled every second when the KVM guest (1 socket, 2 cores, 4 threads,
vCPUs pinned) was idle. The value monotonically increase over time as
expected.
idle_purr:33128550
idle_spurr:3e3c775c
purr:d48181820
spurr:10295e8f28
idle_purr:331319f0
idle_spurr:3e3d56a4
purr:d481c4600
spurr:102964d3f0
idle_purr:331378c0
idle_spurr:3e3de58c
purr:d481faea0
spurr:102969f118
idle_purr:3313daa0
idle_spurr:3e3e77a4
purr:d4822c750
spurr:10296e9538
idle_purr:33143ab0
idle_spurr:3e3f093c
purr:d482608c0
spurr:1029737808
vCPU busy
---------------
Sampled every second on the same KVM guest, when the vCPU was running
a cpu-hog. The values of purr and spurr monotonically increase. And
the values of idle_purr and idle_spurr are stagnant as expected.
idle_purr:3335fca0
idle_spurr:3e71a774
purr:d5dd6bca0
spurr:1049fca1f0
idle_purr:3335fca0
idle_spurr:3e71a774
purr:d7c6f1c50
spurr:1077e12d40
idle_purr:3335fca0
idle_spurr:3e71a774
purr:d9b078720
spurr:10a5c5cc08
idle_purr:3335fca0
idle_spurr:3e71a774
purr:db99ef1d0
spurr:10d3a8eac0
idle_purr:3335fca0
idle_spurr:3e71a774
purr:dd8365c20
spurr:11018c0908
However, I don't think the even the values of PURR or SPURR make any
sense on KVM guest, since the Linux Hypervisor doesn't set additional
registers such as RWMR, except on POWER8, where the KVM sets RWMR
corresponding to the number of online threads in a vCORE before
dispatching the vcore.
On a POWER9 KVM guest:
When it is idle:
# ./purr_tb -t 4
Got threads_per_core = 4
CORE 0:
CPU 0 : Delta PURR : 2371632
CPU 1 : Delta PURR : 5056
CPU 2 : Delta PURR : 8016
CPU 3 : Delta PURR : 12688
Total Delta PURR : 2397392 (Expected ~514567680)
When all the threads are running CPU Hogs:
# ./purr_tb -t 4
Got threads_per_core = 4
CORE 0:
CPU 0 : Delta PURR : 510742304
CPU 1 : Delta PURR : 510747696
CPU 2 : Delta PURR : 510740208
CPU 3 : Delta PURR : 510735200
Total Delta PURR : 2042965408 (Expected ~512289792)
>
>
> >
> > cheers
>
--
Thanks and Regards
gautham.
^ permalink raw reply
* Re: Don't initialise ports with no PHY
From: Christian Zigotzky @ 2020-05-01 5:35 UTC (permalink / raw)
To: Darren Stevens
Cc: Andrew Lunn, linuxppc-dev, mad skateman, R.T.Dickinson, netdev
In-Reply-To: <4f9f12e02c7.744a6d93@auth.smtp.1and1.co.uk>
> On 30. Apr 2020, at 23:36, Darren Stevens <darren@stevens-zone.net> wrote:
>
> Hello Christian
>
>> On 29/04/2020, Christian Zigotzky wrote:
>>
>>
>>>> On 29. Apr 2020, at 17:22, Andrew Lunn <andrew@lunn.ch> wrote:
>>>
>>> ?On Wed, Apr 29, 2020 at 03:55:28PM +0200, Christian Zigotzky wrote:
>>>> Hi Andrew,
>>>>
>>>> You can find some dtb and source files in our kernel package.
>>>>
>>>> Download: http://www.xenosoft.de/linux-image-5.7-rc3-X1000_X5000.tar.gz
>>>
>>> I have the tarball. Are we talking about
>>>
>>>
> linux-image-5.7-rc3-X1000_X5000/X5000_and_QEMU_e5500/dtbs/X5000_20/cyrus.eth.dtb
>>
>>> I don't see any status = "disabled"; in the blob. So i would expect
>>> the driver to probe.
>
> No, the vendor never added that to them.
>
>> Yes, that's correct but maybe Darren uses another dtb file.
>>
>> @Darren
>> Which dtb file do you use?
>
> My current one attached, including updated cyrus_p5020.dts & p5020si-pre.dtsi
> which I'm preparing patches for.
>
> Christian, build an unmodified kernel, select board level reset or power off,
> then both the GPIO drivers.
> Then under LED Support: GPIO connected LED's and triggers -> disk activity
>
> I think you still have a 5020 don't you? I'll look at 5040 later (I'll need
> someone to test)
>
> Regards
> Darren
> <cyrus-dts.zip>
Darren
I use a 5040 currently.
Thanks
Christian
^ permalink raw reply
* [PATCH v7 28/28] powerpc sstep: Add support for prefixed fixed-point arithmetic
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
This adds emulation support for the following prefixed Fixed-Point
Arithmetic instructions:
* Prefixed Add Immediate (paddi)
Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v3: Since we moved the prefixed loads/stores into the load/store switch
statement it no longer makes sense to have paddi in there, so move it
out.
---
arch/powerpc/lib/sstep.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index d50fa2a78866..32e3ba742e55 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1337,6 +1337,26 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
switch (opcode) {
#ifdef __powerpc64__
+ case 1:
+ prefix_r = word & (1ul << 20);
+ ra = (suffix >> 16) & 0x1f;
+ rd = (suffix >> 21) & 0x1f;
+ op->reg = rd;
+ op->val = regs->gpr[rd];
+ suffixopcode = suffix >> 26;
+ prefixtype = (word >> 24) & 0x3;
+ switch (prefixtype) {
+ case 2:
+ if (prefix_r && ra)
+ return 0;
+ switch (suffixopcode) {
+ case 14: /* paddi */
+ op->type = COMPUTE | PREFIXED;
+ op->val = mlsd_8lsd_ea(word, suffix, regs);
+ goto compute_done;
+ }
+ }
+ break;
case 2: /* tdi */
if (rd & trap_compare(regs->gpr[ra], (short) word))
goto trap;
--
2.17.1
^ permalink raw reply related
* [PATCH v7 27/28] powerpc sstep: Add support for prefixed load/stores
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
This adds emulation support for the following prefixed integer
load/stores:
* Prefixed Load Byte and Zero (plbz)
* Prefixed Load Halfword and Zero (plhz)
* Prefixed Load Halfword Algebraic (plha)
* Prefixed Load Word and Zero (plwz)
* Prefixed Load Word Algebraic (plwa)
* Prefixed Load Doubleword (pld)
* Prefixed Store Byte (pstb)
* Prefixed Store Halfword (psth)
* Prefixed Store Word (pstw)
* Prefixed Store Doubleword (pstd)
* Prefixed Load Quadword (plq)
* Prefixed Store Quadword (pstq)
the follow prefixed floating-point load/stores:
* Prefixed Load Floating-Point Single (plfs)
* Prefixed Load Floating-Point Double (plfd)
* Prefixed Store Floating-Point Single (pstfs)
* Prefixed Store Floating-Point Double (pstfd)
and for the following prefixed VSX load/stores:
* Prefixed Load VSX Scalar Doubleword (plxsd)
* Prefixed Load VSX Scalar Single-Precision (plxssp)
* Prefixed Load VSX Vector [0|1] (plxv, plxv0, plxv1)
* Prefixed Store VSX Scalar Doubleword (pstxsd)
* Prefixed Store VSX Scalar Single-Precision (pstxssp)
* Prefixed Store VSX Vector [0|1] (pstxv, pstxv0, pstxv1)
Reviewed-by: Balamuruhan S <bala24@linux.ibm.com>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v2: - Combine all load/store patches
- Fix the name of Type 01 instructions
- Remove sign extension flag from pstd/pld
- Rename sufx -> suffix
v3: - Move prefixed loads and stores into the switch statement
v6: - Compile on ppc32
- Add back in + GETLENGTH(op->type)
---
arch/powerpc/include/asm/sstep.h | 4 +
arch/powerpc/lib/sstep.c | 165 ++++++++++++++++++++++++++++++-
2 files changed, 167 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
index c3ce903ac488..9b200a5f8794 100644
--- a/arch/powerpc/include/asm/sstep.h
+++ b/arch/powerpc/include/asm/sstep.h
@@ -90,11 +90,15 @@ enum instruction_type {
#define VSX_LDLEFT 4 /* load VSX register from left */
#define VSX_CHECK_VEC 8 /* check MSR_VEC not MSR_VSX for reg >= 32 */
+/* Prefixed flag, ORed in with type */
+#define PREFIXED 0x800
+
/* Size field in type word */
#define SIZE(n) ((n) << 12)
#define GETSIZE(w) ((w) >> 12)
#define GETTYPE(t) ((t) & INSTR_TYPE_MASK)
+#define GETLENGTH(t) (((t) & PREFIXED) ? 8 : 4)
#define MKOP(t, f, s) ((t) | (f) | SIZE(s))
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index ecd756c346fd..d50fa2a78866 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -187,6 +187,44 @@ static nokprobe_inline unsigned long xform_ea(unsigned int instr,
return ea;
}
+/*
+ * Calculate effective address for a MLS:D-form / 8LS:D-form
+ * prefixed instruction
+ */
+static nokprobe_inline unsigned long mlsd_8lsd_ea(unsigned int instr,
+ unsigned int suffix,
+ const struct pt_regs *regs)
+{
+ int ra, prefix_r;
+ unsigned int dd;
+ unsigned long ea, d0, d1, d;
+
+ prefix_r = instr & (1ul << 20);
+ ra = (suffix >> 16) & 0x1f;
+
+ d0 = instr & 0x3ffff;
+ d1 = suffix & 0xffff;
+ d = (d0 << 16) | d1;
+
+ /*
+ * sign extend a 34 bit number
+ */
+ dd = (unsigned int)(d >> 2);
+ ea = (signed int)dd;
+ ea = (ea << 2) | (d & 0x3);
+
+ if (!prefix_r && ra)
+ ea += regs->gpr[ra];
+ else if (!prefix_r && !ra)
+ ; /* Leave ea as is */
+ else if (prefix_r && !ra)
+ ea += regs->nip;
+ else if (prefix_r && ra)
+ ; /* Invalid form. Should already be checked for by caller! */
+
+ return ea;
+}
+
/*
* Return the largest power of 2, not greater than sizeof(unsigned long),
* such that x is a multiple of it.
@@ -1166,6 +1204,9 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
struct ppc_inst instr)
{
unsigned int opcode, ra, rb, rc, rd, spr, u;
+#ifdef __powerpc64__
+ unsigned int suffixopcode, prefixtype, prefix_r;
+#endif
unsigned long int imm;
unsigned long int val, val2;
unsigned int mb, me, sh;
@@ -2652,6 +2693,126 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
break;
}
break;
+ case 1: /* Prefixed instructions */
+ prefix_r = word & (1ul << 20);
+ ra = (suffix >> 16) & 0x1f;
+ op->update_reg = ra;
+ rd = (suffix >> 21) & 0x1f;
+ op->reg = rd;
+ op->val = regs->gpr[rd];
+
+ suffixopcode = suffix >> 26;
+ prefixtype = (word >> 24) & 0x3;
+ switch (prefixtype) {
+ case 0: /* Type 00 Eight-Byte Load/Store */
+ if (prefix_r && ra)
+ break;
+ op->ea = mlsd_8lsd_ea(word, suffix, regs);
+ switch (suffixopcode) {
+ case 41: /* plwa */
+ op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 4);
+ break;
+ case 42: /* plxsd */
+ op->reg = rd + 32;
+ op->type = MKOP(LOAD_VSX, PREFIXED, 8);
+ op->element_size = 8;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 43: /* plxssp */
+ op->reg = rd + 32;
+ op->type = MKOP(LOAD_VSX, PREFIXED, 4);
+ op->element_size = 8;
+ op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
+ break;
+ case 46: /* pstxsd */
+ op->reg = rd + 32;
+ op->type = MKOP(STORE_VSX, PREFIXED, 8);
+ op->element_size = 8;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 47: /* pstxssp */
+ op->reg = rd + 32;
+ op->type = MKOP(STORE_VSX, PREFIXED, 4);
+ op->element_size = 8;
+ op->vsx_flags = VSX_FPCONV | VSX_CHECK_VEC;
+ break;
+ case 51: /* plxv1 */
+ op->reg += 32;
+
+ /* fallthru */
+ case 50: /* plxv0 */
+ op->type = MKOP(LOAD_VSX, PREFIXED, 16);
+ op->element_size = 16;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 55: /* pstxv1 */
+ op->reg = rd + 32;
+
+ /* fallthru */
+ case 54: /* pstxv0 */
+ op->type = MKOP(STORE_VSX, PREFIXED, 16);
+ op->element_size = 16;
+ op->vsx_flags = VSX_CHECK_VEC;
+ break;
+ case 56: /* plq */
+ op->type = MKOP(LOAD, PREFIXED, 16);
+ break;
+ case 57: /* pld */
+ op->type = MKOP(LOAD, PREFIXED, 8);
+ break;
+ case 60: /* stq */
+ op->type = MKOP(STORE, PREFIXED, 16);
+ break;
+ case 61: /* pstd */
+ op->type = MKOP(STORE, PREFIXED, 8);
+ break;
+ }
+ break;
+ case 1: /* Type 01 Eight-Byte Register-to-Register */
+ break;
+ case 2: /* Type 10 Modified Load/Store */
+ if (prefix_r && ra)
+ break;
+ op->ea = mlsd_8lsd_ea(word, suffix, regs);
+ switch (suffixopcode) {
+ case 32: /* plwz */
+ op->type = MKOP(LOAD, PREFIXED, 4);
+ break;
+ case 34: /* plbz */
+ op->type = MKOP(LOAD, PREFIXED, 1);
+ break;
+ case 36: /* pstw */
+ op->type = MKOP(STORE, PREFIXED, 4);
+ break;
+ case 38: /* pstb */
+ op->type = MKOP(STORE, PREFIXED, 1);
+ break;
+ case 40: /* plhz */
+ op->type = MKOP(LOAD, PREFIXED, 2);
+ break;
+ case 42: /* plha */
+ op->type = MKOP(LOAD, PREFIXED | SIGNEXT, 2);
+ break;
+ case 44: /* psth */
+ op->type = MKOP(STORE, PREFIXED, 2);
+ break;
+ case 48: /* plfs */
+ op->type = MKOP(LOAD_FP, PREFIXED | FPCONV, 4);
+ break;
+ case 50: /* plfd */
+ op->type = MKOP(LOAD_FP, PREFIXED, 8);
+ break;
+ case 52: /* pstfs */
+ op->type = MKOP(STORE_FP, PREFIXED | FPCONV, 4);
+ break;
+ case 54: /* pstfd */
+ op->type = MKOP(STORE_FP, PREFIXED, 8);
+ break;
+ }
+ break;
+ case 3: /* Type 11 Modified Register-to-Register */
+ break;
+ }
#endif /* __powerpc64__ */
}
@@ -2760,7 +2921,7 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
{
unsigned long next_pc;
- next_pc = truncate_if_32bit(regs->msr, regs->nip + 4);
+ next_pc = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op->type));
switch (GETTYPE(op->type)) {
case COMPUTE:
if (op->type & SETREG)
@@ -3205,7 +3366,7 @@ int emulate_step(struct pt_regs *regs, struct ppc_inst instr)
return 0;
instr_done:
- regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);
+ regs->nip = truncate_if_32bit(regs->msr, regs->nip + GETLENGTH(op.type));
return 1;
}
NOKPROBE_SYMBOL(emulate_step);
--
2.17.1
^ permalink raw reply related
* [PATCH v7 26/28] powerpc: Support prefixed instructions in alignment handler
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
If a prefixed instruction results in an alignment exception, the
SRR1_PREFIXED bit is set. The handler attempts to emulate the
responsible instruction and then increment the NIP past it. Use
SRR1_PREFIXED to determine by how much the NIP should be incremented.
Prefixed instructions are not permitted to cross 64-byte boundaries. If
they do the alignment interrupt is invoked with SRR1 BOUNDARY bit set.
If this occurs send a SIGBUS to the offending process if in user mode.
If in kernel mode call bad_page_fault().
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v2: - Move __get_user_instr() and __get_user_instr_inatomic() to this
commit (previously in "powerpc sstep: Prepare to support prefixed
instructions").
- Rename sufx to suffix
- Use a macro for calculating instruction length
v3: Move __get_user_{instr(), instr_inatomic()} up with the other
get_user definitions and remove nested if.
v4: Rolled into "Add prefixed instructions to instruction data type"
v5: Only one definition of inst_length()
---
arch/powerpc/kernel/traps.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 493a3fa0ac1a..105242cc2f28 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -583,6 +583,8 @@ static inline int check_io_access(struct pt_regs *regs)
#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
#define REASON_PRIVILEGED ESR_PPR
#define REASON_TRAP ESR_PTR
+#define REASON_PREFIXED 0
+#define REASON_BOUNDARY 0
/* single-step stuff */
#define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC)
@@ -597,12 +599,16 @@ static inline int check_io_access(struct pt_regs *regs)
#define REASON_ILLEGAL SRR1_PROGILL
#define REASON_PRIVILEGED SRR1_PROGPRIV
#define REASON_TRAP SRR1_PROGTRAP
+#define REASON_PREFIXED SRR1_PREFIXED
+#define REASON_BOUNDARY SRR1_BOUNDARY
#define single_stepping(regs) ((regs)->msr & MSR_SE)
#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
#define clear_br_trace(regs) ((regs)->msr &= ~MSR_BE)
#endif
+#define inst_length(reason) (((reason) & REASON_PREFIXED) ? 8 : 4)
+
#if defined(CONFIG_E500)
int machine_check_e500mc(struct pt_regs *regs)
{
@@ -1593,11 +1599,20 @@ void alignment_exception(struct pt_regs *regs)
{
enum ctx_state prev_state = exception_enter();
int sig, code, fixed = 0;
+ unsigned long reason;
/* We restore the interrupt state now */
if (!arch_irq_disabled_regs(regs))
local_irq_enable();
+ reason = get_reason(regs);
+
+ if (reason & REASON_BOUNDARY) {
+ sig = SIGBUS;
+ code = BUS_ADRALN;
+ goto bad;
+ }
+
if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT))
goto bail;
@@ -1606,7 +1621,8 @@ void alignment_exception(struct pt_regs *regs)
fixed = fix_alignment(regs);
if (fixed == 1) {
- regs->nip += 4; /* skip over emulated instruction */
+ /* skip over emulated instruction */
+ regs->nip += inst_length(reason);
emulate_single_step(regs);
goto bail;
}
@@ -1619,6 +1635,7 @@ void alignment_exception(struct pt_regs *regs)
sig = SIGBUS;
code = BUS_ADRALN;
}
+bad:
if (user_mode(regs))
_exception(sig, regs, code, regs->dar);
else
--
2.17.1
^ permalink raw reply related
* [PATCH v7 25/28] powerpc: Test prefixed instructions in feature fixups
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
Expand the feature-fixups self-tests to includes tests for prefixed
instructions.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: New to series
---
arch/powerpc/lib/feature-fixups-test.S | 68 +++++++++++++++++++++++
arch/powerpc/lib/feature-fixups.c | 74 ++++++++++++++++++++++++++
2 files changed, 142 insertions(+)
diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S
index b12168c2447a..6e2da9123a9b 100644
--- a/arch/powerpc/lib/feature-fixups-test.S
+++ b/arch/powerpc/lib/feature-fixups-test.S
@@ -791,3 +791,71 @@ globl(lwsync_fixup_test_expected_SYNC)
1: or 1,1,1
sync
+globl(ftr_fixup_prefix1)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000000
+ or 2,2,2
+globl(end_ftr_fixup_prefix1)
+
+globl(ftr_fixup_prefix1_orig)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000000
+ or 2,2,2
+
+globl(ftr_fixup_prefix1_expected)
+ or 1,1,1
+ nop
+ nop
+ or 2,2,2
+
+globl(ftr_fixup_prefix2)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000000
+ or 2,2,2
+globl(end_ftr_fixup_prefix2)
+
+globl(ftr_fixup_prefix2_orig)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000000
+ or 2,2,2
+
+globl(ftr_fixup_prefix2_alt)
+ .long 0x7000000
+ .long 0x0000001
+
+globl(ftr_fixup_prefix2_expected)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000001
+ or 2,2,2
+
+globl(ftr_fixup_prefix3)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000000
+ or 2,2,2
+ or 3,3,3
+globl(end_ftr_fixup_prefix3)
+
+globl(ftr_fixup_prefix3_orig)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000000
+ or 2,2,2
+ or 3,3,3
+
+globl(ftr_fixup_prefix3_alt)
+ .long 1 << 26
+ .long 0x0000001
+ nop
+
+globl(ftr_fixup_prefix3_expected)
+ or 1,1,1
+ .long 1 << 26
+ .long 0x0000001
+ nop
+ or 3,3,3
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 243011f85287..6fc499b1d63e 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -687,6 +687,75 @@ static void test_lwsync_macros(void)
}
}
+#ifdef __powerpc64__
+static void __init test_prefix_patching(void)
+{
+ extern unsigned int ftr_fixup_prefix1[];
+ extern unsigned int end_ftr_fixup_prefix1[];
+ extern unsigned int ftr_fixup_prefix1_orig[];
+ extern unsigned int ftr_fixup_prefix1_expected[];
+ int size = sizeof(unsigned int) * (end_ftr_fixup_prefix1 - ftr_fixup_prefix1);
+
+ fixup.value = fixup.mask = 8;
+ fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix1 + 1);
+ fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix1 + 3);
+ fixup.alt_start_off = fixup.alt_end_off = 0;
+
+ /* Sanity check */
+ check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_orig, size) == 0);
+
+ patch_feature_section(0, &fixup);
+ check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_expected, size) == 0);
+ check(memcmp(ftr_fixup_prefix1, ftr_fixup_prefix1_orig, size) != 0);
+}
+
+static void __init test_prefix_alt_patching(void)
+{
+ extern unsigned int ftr_fixup_prefix2[];
+ extern unsigned int end_ftr_fixup_prefix2[];
+ extern unsigned int ftr_fixup_prefix2_orig[];
+ extern unsigned int ftr_fixup_prefix2_expected[];
+ extern unsigned int ftr_fixup_prefix2_alt[];
+ int size = sizeof(unsigned int) * (end_ftr_fixup_prefix2 - ftr_fixup_prefix2);
+
+ fixup.value = fixup.mask = 8;
+ fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix2 + 1);
+ fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix2 + 3);
+ fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_prefix2_alt);
+ fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_prefix2_alt + 2);
+ /* Sanity check */
+ check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_orig, size) == 0);
+
+ patch_feature_section(0, &fixup);
+ check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_expected, size) == 0);
+ patch_feature_section(0, &fixup);
+ check(memcmp(ftr_fixup_prefix2, ftr_fixup_prefix2_orig, size) != 0);
+}
+
+static void __init test_prefix_word_alt_patching(void)
+{
+ extern unsigned int ftr_fixup_prefix3[];
+ extern unsigned int end_ftr_fixup_prefix3[];
+ extern unsigned int ftr_fixup_prefix3_orig[];
+ extern unsigned int ftr_fixup_prefix3_expected[];
+ extern unsigned int ftr_fixup_prefix3_alt[];
+ int size = sizeof(unsigned int) * (end_ftr_fixup_prefix3 - ftr_fixup_prefix3);
+
+ fixup.value = fixup.mask = 8;
+ fixup.start_off = calc_offset(&fixup, ftr_fixup_prefix3 + 1);
+ fixup.end_off = calc_offset(&fixup, ftr_fixup_prefix3 + 4);
+ fixup.alt_start_off = calc_offset(&fixup, ftr_fixup_prefix3_alt);
+ fixup.alt_end_off = calc_offset(&fixup, ftr_fixup_prefix3_alt + 3);
+ /* Sanity check */
+ check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) == 0);
+
+ patch_feature_section(0, &fixup);
+ check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_expected, size) == 0);
+ patch_feature_section(0, &fixup);
+ check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) != 0);
+}
+#endif /* __powerpc64__ */
+
static int __init test_feature_fixups(void)
{
printk(KERN_DEBUG "Running feature fixup self-tests ...\n");
@@ -701,6 +770,11 @@ static int __init test_feature_fixups(void)
test_cpu_macros();
test_fw_macros();
test_lwsync_macros();
+#ifdef __powerpc64__
+ test_prefix_patching();
+ test_prefix_alt_patching();
+ test_prefix_word_alt_patching();
+#endif
return 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v7 24/28] powerpc: Test prefixed code patching
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
Expand the code-patching self-tests to includes tests for patching
prefixed instructions.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v6: New to series
---
arch/powerpc/lib/Makefile | 2 +-
arch/powerpc/lib/code-patching.c | 21 +++++++++++++++++++++
arch/powerpc/lib/test_code-patching.S | 19 +++++++++++++++++++
3 files changed, 41 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/lib/test_code-patching.S
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 546591848219..5e994cda8e40 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
endif
-obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o
+obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o test_code-patching.o
ifndef CONFIG_KASAN
obj-y += string.o memcmp_$(BITS).o
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index b32fa707725e..7107c6d01261 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -699,6 +699,24 @@ static void __init test_translate_branch(void)
vfree(buf);
}
+#ifdef __powerpc64__
+static void __init test_prefixed_patching(void)
+{
+ extern unsigned int code_patching_test1[];
+ extern unsigned int code_patching_test1_expected[];
+ extern unsigned int end_code_patching_test1[];
+
+ __patch_instruction((struct ppc_inst *)code_patching_test1,
+ ppc_inst_prefix(1 << 26, 0x00000000),
+ (struct ppc_inst *)code_patching_test1);
+
+ check(!memcmp(code_patching_test1,
+ code_patching_test1_expected,
+ sizeof(unsigned int) *
+ (end_code_patching_test1 - code_patching_test1)));
+}
+#endif
+
static int __init test_code_patching(void)
{
printk(KERN_DEBUG "Running code patching self-tests ...\n");
@@ -707,6 +725,9 @@ static int __init test_code_patching(void)
test_branch_bform();
test_create_function_call();
test_translate_branch();
+#ifdef __powerpc64__
+ test_prefixed_patching();
+#endif
return 0;
}
diff --git a/arch/powerpc/lib/test_code-patching.S b/arch/powerpc/lib/test_code-patching.S
new file mode 100644
index 000000000000..91aab208a804
--- /dev/null
+++ b/arch/powerpc/lib/test_code-patching.S
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020 IBM Corporation
+ */
+
+ .text
+
+#define globl(x) \
+ .globl x; \
+x:
+
+globl(code_patching_test1)
+ nop
+ nop
+globl(end_code_patching_test1)
+
+globl(code_patching_test1_expected)
+ .long 1 << 26
+ .long 0x0000000
--
2.17.1
^ permalink raw reply related
* [PATCH v7 23/28] powerpc: Add prefixed instructions to instruction data type
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
For powerpc64, redefine the ppc_inst type so both word and prefixed
instructions can be represented. On powerpc32 the type will remain the
same. Update places which had assumed instructions to be 4 bytes long.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4: New to series
v5: - Distinguish normal instructions from prefixed instructions with a
0xff marker for the suffix.
- __patch_instruction() using std for prefixed instructions
v6: - Return false instead of 0 in ppc_inst_prefixed()
- Fix up types for ppc32 so it compiles
- remove ppc_inst_write()
- __patching_instruction(): move flush out of condition
---
arch/powerpc/include/asm/inst.h | 68 +++++++++++++++++++++++++---
arch/powerpc/include/asm/kprobes.h | 2 +-
arch/powerpc/include/asm/uaccess.h | 32 ++++++++++++-
arch/powerpc/include/asm/uprobes.h | 2 +-
arch/powerpc/kernel/optprobes.c | 42 +++++++++--------
arch/powerpc/kernel/optprobes_head.S | 3 ++
arch/powerpc/lib/code-patching.c | 13 ++++--
arch/powerpc/lib/feature-fixups.c | 5 +-
arch/powerpc/lib/inst.c | 40 ++++++++++++++++
arch/powerpc/lib/sstep.c | 4 +-
arch/powerpc/xmon/xmon.c | 4 +-
arch/powerpc/xmon/xmon_bpts.S | 2 +
12 files changed, 180 insertions(+), 37 deletions(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h
index 2f3c9d5bcf7c..1e743635c214 100644
--- a/arch/powerpc/include/asm/inst.h
+++ b/arch/powerpc/include/asm/inst.h
@@ -8,23 +8,72 @@
struct ppc_inst {
u32 val;
+#ifdef __powerpc64__
+ u32 suffix;
+#endif /* __powerpc64__ */
} __packed;
-#define ppc_inst(x) ((struct ppc_inst){ .val = x })
-
static inline u32 ppc_inst_val(struct ppc_inst x)
{
return x.val;
}
-static inline int ppc_inst_len(struct ppc_inst x)
+static inline int ppc_inst_primary_opcode(struct ppc_inst x)
{
- return sizeof(struct ppc_inst);
+ return ppc_inst_val(x) >> 26;
}
-static inline int ppc_inst_primary_opcode(struct ppc_inst x)
+#ifdef __powerpc64__
+#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff })
+
+#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) })
+
+static inline u32 ppc_inst_suffix(struct ppc_inst x)
{
- return ppc_inst_val(x) >> 26;
+ return x.suffix;
+}
+
+static inline bool ppc_inst_prefixed(struct ppc_inst x)
+{
+ return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != 0xff;
+}
+
+static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
+{
+ return ppc_inst_prefix(swab32(ppc_inst_val(x)),
+ swab32(ppc_inst_suffix(x)));
+}
+
+static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr)
+{
+ u32 val, suffix;
+
+ val = *(u32 *)ptr;
+ if ((val >> 26) == 1) {
+ suffix = *((u32 *)ptr + 1);
+ return ppc_inst_prefix(val, suffix);
+ } else {
+ return ppc_inst(val);
+ }
+}
+
+static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
+{
+ return *(u64 *)&x == *(u64 *)&y;
+}
+
+#else
+
+#define ppc_inst(x) ((struct ppc_inst){ .val = x })
+
+static inline bool ppc_inst_prefixed(struct ppc_inst x)
+{
+ return false;
+}
+
+static inline u32 ppc_inst_suffix(struct ppc_inst x)
+{
+ return 0;
}
static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x)
@@ -42,6 +91,13 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y)
return ppc_inst_val(x) == ppc_inst_val(y);
}
+#endif /* __powerpc64__ */
+
+static inline int ppc_inst_len(struct ppc_inst x)
+{
+ return (ppc_inst_prefixed(x)) ? 8 : 4;
+}
+
int probe_user_read_inst(struct ppc_inst *inst,
struct ppc_inst *nip);
int probe_kernel_read_inst(struct ppc_inst *inst,
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 66b3f2983b22..4fc0e15e23a5 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -43,7 +43,7 @@ extern kprobe_opcode_t optprobe_template_ret[];
extern kprobe_opcode_t optprobe_template_end[];
/* Fixed instruction size for powerpc */
-#define MAX_INSN_SIZE 1
+#define MAX_INSN_SIZE 2
#define MAX_OPTIMIZED_LENGTH sizeof(kprobe_opcode_t) /* 4 bytes */
#define MAX_OPTINSN_SIZE (optprobe_template_end - optprobe_template_entry)
#define RELATIVEJUMP_SIZE sizeof(kprobe_opcode_t) /* 4 bytes */
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index c0a35e4586a5..12e52aa179b6 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -105,11 +105,41 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
#define __put_user_inatomic(x, ptr) \
__put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+#ifdef __powerpc64__
+#define __get_user_instr(x, ptr) \
+({ \
+ long __gui_ret = 0; \
+ unsigned int prefix, suffix; \
+ __gui_ret = __get_user(prefix, (unsigned int __user *)ptr); \
+ if (!__gui_ret && (prefix >> 26) == 1) { \
+ __gui_ret = __get_user(suffix, (unsigned int __user *)ptr + 1); \
+ (x) = ppc_inst_prefix(prefix, suffix); \
+ } else { \
+ (x) = ppc_inst(prefix); \
+ } \
+ __gui_ret; \
+})
+
+#define __get_user_instr_inatomic(x, ptr) \
+({ \
+ long __gui_ret = 0; \
+ unsigned int prefix, suffix; \
+ __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)ptr); \
+ if (!__gui_ret && (prefix >> 26) == 1) { \
+ __gui_ret = __get_user_inatomic(suffix, (unsigned int __user *)ptr + 1); \
+ (x) = ppc_inst_prefix(prefix, suffix); \
+ } else { \
+ (x) = ppc_inst(prefix); \
+ } \
+ __gui_ret; \
+})
+#else
#define __get_user_instr(x, ptr) \
__get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true)
-
#define __get_user_instr_inatomic(x, ptr) \
__get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32))
+#endif
+
extern long __put_user_bad(void);
/*
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
index 7e3b329ba2d3..5bf65f5d44a9 100644
--- a/arch/powerpc/include/asm/uprobes.h
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -15,7 +15,7 @@
typedef ppc_opcode_t uprobe_opcode_t;
-#define MAX_UINSN_BYTES 4
+#define MAX_UINSN_BYTES 8
#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
/* The following alias is needed for reference from arch-agnostic code */
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index d704f9598f48..a67c5288cf50 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -159,38 +159,38 @@ void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
/*
* Generate instructions to load provided immediate 64-bit value
- * to register 'r3' and patch these instructions at 'addr'.
+ * to register 'reg' and patch these instructions at 'addr'.
*/
-void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
+void patch_imm64_load_insns(unsigned long val, int reg, kprobe_opcode_t *addr)
{
- /* lis r3,(op)@highest */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(3) |
+ /* lis reg,(op)@highest */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ADDIS | ___PPC_RT(reg) |
((val >> 48) & 0xffff)));
addr++;
- /* ori r3,r3,(op)@higher */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 32) & 0xffff)));
+ /* ori reg,reg,(op)@higher */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | ((val >> 32) & 0xffff)));
addr++;
- /* rldicr r3,r3,32,31 */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(3) |
- ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)));
+ /* rldicr reg,reg,32,31 */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_RLDICR | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | __PPC_SH64(32) | __PPC_ME64(31)));
addr++;
- /* oris r3,r3,(op)@h */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 16) & 0xffff)));
+ /* oris reg,reg,(op)@h */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORIS | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | ((val >> 16) & 0xffff)));
addr++;
- /* ori r3,r3,(op)@l */
- patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | (val & 0xffff)));
+ /* ori reg,reg,(op)@l */
+ patch_instruction((struct ppc_inst *)addr, ppc_inst(PPC_INST_ORI | ___PPC_RA(reg) |
+ ___PPC_RS(reg) | (val & 0xffff)));
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
{
- struct ppc_inst branch_op_callback, branch_emulate_step;
+ struct ppc_inst branch_op_callback, branch_emulate_step, temp;
kprobe_opcode_t *op_callback_addr, *emulate_step_addr, *buff;
long b_offset;
unsigned long nip, size;
@@ -240,7 +240,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
* Fixup the template with instructions to:
* 1. load the address of the actual probepoint
*/
- patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
+ patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX);
/*
* 2. branch to optimized_callback() and emulate_step()
@@ -271,7 +271,11 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
/*
* 3. load instruction to be emulated into relevant register, and
*/
- patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
+ temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn);
+ patch_imm64_load_insns(ppc_inst_val(temp) |
+ ((u64)ppc_inst_suffix(temp) << 32),
+ 4,
+ buff + TMPL_INSN_IDX);
/*
* 4. branch back from trampoline
diff --git a/arch/powerpc/kernel/optprobes_head.S b/arch/powerpc/kernel/optprobes_head.S
index cf383520843f..ff8ba4d3824d 100644
--- a/arch/powerpc/kernel/optprobes_head.S
+++ b/arch/powerpc/kernel/optprobes_head.S
@@ -94,6 +94,9 @@ optprobe_template_insn:
/* 2, Pass instruction to be emulated in r4 */
nop
nop
+ nop
+ nop
+ nop
.global optprobe_template_call_emulate
optprobe_template_call_emulate:
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 5b2f66d06b1e..b32fa707725e 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -24,13 +24,18 @@ static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst instr
{
int err = 0;
- __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
- if (err)
- return err;
+ if (!ppc_inst_prefixed(instr)) {
+ __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw");
+ if (err)
+ return err;
+ } else {
+ __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | ppc_inst_val(instr), patch_addr, err, "std");
+ if (err)
+ return err;
+ }
asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr),
"r" (exec_addr));
-
return 0;
}
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index f4845e740338..243011f85287 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -84,12 +84,13 @@ static int patch_feature_section(unsigned long value, struct fixup_entry *fcur)
src = alt_start;
dest = start;
- for (; src < alt_end; src++, dest++) {
+ for (; src < alt_end; src = (void *)src + ppc_inst_len(ppc_inst_read(src)),
+ (dest = (void *)dest + ppc_inst_len(ppc_inst_read(dest)))) {
if (patch_alt_instruction(src, dest, alt_start, alt_end))
return 1;
}
- for (; dest < end; dest++)
+ for (; dest < end; dest = (void *)dest + ppc_inst_len(ppc_inst(PPC_INST_NOP)))
raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP));
return 0;
diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c
index 08dedd927268..71101791edcc 100644
--- a/arch/powerpc/lib/inst.c
+++ b/arch/powerpc/lib/inst.c
@@ -6,6 +6,45 @@
#include <linux/uaccess.h>
#include <asm/inst.h>
+#ifdef __powerpc64__
+int probe_user_read_inst(struct ppc_inst *inst,
+ struct ppc_inst *nip)
+{
+ unsigned int val, suffix;
+ int err;
+
+ err = probe_user_read(&val, nip, sizeof(val));
+ if (err)
+ return err;
+ if ((val >> 26) == 1) {
+ err = probe_user_read(&suffix, (void *)nip+4,
+ sizeof(unsigned int));
+ *inst = ppc_inst_prefix(val, suffix);
+ } else {
+ *inst = ppc_inst(val);
+ }
+ return err;
+}
+
+int probe_kernel_read_inst(struct ppc_inst *inst,
+ struct ppc_inst *src)
+{
+ unsigned int val, suffix;
+ int err;
+
+ err = probe_kernel_read(&val, src, sizeof(val));
+ if (err)
+ return err;
+ if ((val >> 26) == 1) {
+ err = probe_kernel_read(&suffix, (void *)src+4,
+ sizeof(unsigned int));
+ *inst = ppc_inst_prefix(val, suffix);
+ } else {
+ *inst = ppc_inst(val);
+ }
+ return err;
+}
+#else
int probe_user_read_inst(struct ppc_inst *inst,
struct ppc_inst *nip)
{
@@ -27,3 +66,4 @@ int probe_kernel_read_inst(struct ppc_inst *inst,
*inst = ppc_inst(val);
return err;
}
+#endif /* __powerpc64__ */
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 95a56bb1ba3f..ecd756c346fd 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1169,10 +1169,12 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
unsigned long int imm;
unsigned long int val, val2;
unsigned int mb, me, sh;
- unsigned int word;
+ unsigned int word, suffix;
long ival;
word = ppc_inst_val(instr);
+ suffix = ppc_inst_suffix(instr);
+
op->type = COMPUTE;
opcode = ppc_inst_primary_opcode(instr);
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index fb2563079046..1d6e66eb2dab 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -758,8 +758,8 @@ static int xmon_bpt(struct pt_regs *regs)
/* Are we at the trap at bp->instr[1] for some bp? */
bp = in_breakpoint_table(regs->nip, &offset);
- if (bp != NULL && offset == 4) {
- regs->nip = bp->address + 4;
+ if (bp != NULL && (offset == 4 || offset == 8)) {
+ regs->nip = bp->address + offset;
atomic_dec(&bp->ref_count);
return 1;
}
diff --git a/arch/powerpc/xmon/xmon_bpts.S b/arch/powerpc/xmon/xmon_bpts.S
index f3ad0ab50854..69726814cd27 100644
--- a/arch/powerpc/xmon/xmon_bpts.S
+++ b/arch/powerpc/xmon/xmon_bpts.S
@@ -4,6 +4,8 @@
#include <asm/asm-offsets.h>
#include "xmon_bpts.h"
+/* Prefixed instructions can not cross 64 byte boundaries */
+.align 6
.global bpt_table
bpt_table:
.space NBPTS * BPT_SIZE
--
2.17.1
^ permalink raw reply related
* [PATCH v7 22/28] powerpc: Define new SRR1 bits for a future ISA version
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
Add the BOUNDARY SRR1 bit definition for when the cause of an alignment
exception is a prefixed instruction that crosses a 64-byte boundary.
Add the PREFIXED SRR1 bit definition for exceptions caused by prefixed
instructions.
Bit 35 of SRR1 is called SRR1_ISI_N_OR_G. This name comes from it being
used to indicate that an ISI was due to the access being no-exec or
guarded. A future ISA version adds another purpose. It is also set if
there is an access in a cache-inhibited location for prefixed
instruction. Rename from SRR1_ISI_N_OR_G to SRR1_ISI_N_G_OR_CIP.
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v2: Combined all the commits concerning SRR1 bits.
---
arch/powerpc/include/asm/reg.h | 4 +++-
arch/powerpc/kvm/book3s_hv_nested.c | 2 +-
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 773f76402392..f95eb8f97756 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -762,7 +762,7 @@
#endif
#define SRR1_ISI_NOPT 0x40000000 /* ISI: Not found in hash */
-#define SRR1_ISI_N_OR_G 0x10000000 /* ISI: Access is no-exec or G */
+#define SRR1_ISI_N_G_OR_CIP 0x10000000 /* ISI: Access is no-exec or G or CI for a prefixed instruction */
#define SRR1_ISI_PROT 0x08000000 /* ISI: Other protection fault */
#define SRR1_WAKEMASK 0x00380000 /* reason for wakeup */
#define SRR1_WAKEMASK_P8 0x003c0000 /* reason for wakeup on POWER8 and 9 */
@@ -789,6 +789,8 @@
#define SRR1_PROGADDR 0x00010000 /* SRR0 contains subsequent addr */
#define SRR1_MCE_MCP 0x00080000 /* Machine check signal caused interrupt */
+#define SRR1_BOUNDARY 0x10000000 /* Prefixed instruction crosses 64-byte boundary */
+#define SRR1_PREFIXED 0x20000000 /* Exception caused by prefixed instruction */
#define SPRN_HSRR0 0x13A /* Save/Restore Register 0 */
#define SPRN_HSRR1 0x13B /* Save/Restore Register 1 */
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index dc97e5be76f6..6ab685227574 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -1169,7 +1169,7 @@ static int kvmhv_translate_addr_nested(struct kvm_vcpu *vcpu,
} else if (vcpu->arch.trap == BOOK3S_INTERRUPT_H_INST_STORAGE) {
/* Can we execute? */
if (!gpte_p->may_execute) {
- flags |= SRR1_ISI_N_OR_G;
+ flags |= SRR1_ISI_N_G_OR_CIP;
goto forward_to_l1;
}
} else {
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 220305454c23..b53a9f1c1a46 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -1260,7 +1260,7 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
status &= ~DSISR_NOHPTE; /* DSISR_NOHPTE == SRR1_ISI_NOPT */
if (!data) {
if (gr & (HPTE_R_N | HPTE_R_G))
- return status | SRR1_ISI_N_OR_G;
+ return status | SRR1_ISI_N_G_OR_CIP;
if (!hpte_read_permission(pp, slb_v & key))
return status | SRR1_ISI_PROT;
} else if (status & DSISR_ISSTORE) {
--
2.17.1
^ permalink raw reply related
* [PATCH v7 21/28] powerpc: Enable Prefixed Instructions
From: Jordan Niethe @ 2020-05-01 3:42 UTC (permalink / raw)
To: linuxppc-dev; +Cc: alistair, npiggin, bala24, naveen.n.rao, Jordan Niethe, dja
In-Reply-To: <20200501034220.8982-1-jniethe5@gmail.com>
From: Alistair Popple <alistair@popple.id.au>
Prefix instructions have their own FSCR bit which needs to enabled via
a CPU feature. The kernel will save the FSCR for problem state but it
needs to be enabled initially.
If prefixed instructions are made unavailable by the [H]FSCR, attempting
to use them will cause a facility unavailable exception. Add "PREFIX" to
the facility_strings[].
Currently there are no prefixed instructions that are actually emulated
by emulate_instruction() within facility_unavailable_exception().
However, when caused by a prefixed instructions the SRR1 PREFIXED bit is
set. Prepare for dealing with emulated prefixed instructions by checking
for this bit.
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
v4:
- Squash "Check for prefixed instructions in
facility_unavailable_exception()" here
- Remove dt parts for now
---
arch/powerpc/include/asm/reg.h | 3 +++
arch/powerpc/kernel/traps.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index da5cab038e25..773f76402392 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -397,6 +397,7 @@
#define SPRN_RWMR 0x375 /* Region-Weighting Mode Register */
/* HFSCR and FSCR bit numbers are the same */
+#define FSCR_PREFIX_LG 13 /* Enable Prefix Instructions */
#define FSCR_SCV_LG 12 /* Enable System Call Vectored */
#define FSCR_MSGP_LG 10 /* Enable MSGP */
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
@@ -408,11 +409,13 @@
#define FSCR_VECVSX_LG 1 /* Enable VMX/VSX */
#define FSCR_FP_LG 0 /* Enable Floating Point */
#define SPRN_FSCR 0x099 /* Facility Status & Control Register */
+#define FSCR_PREFIX __MASK(FSCR_PREFIX_LG)
#define FSCR_SCV __MASK(FSCR_SCV_LG)
#define FSCR_TAR __MASK(FSCR_TAR_LG)
#define FSCR_EBB __MASK(FSCR_EBB_LG)
#define FSCR_DSCR __MASK(FSCR_DSCR_LG)
#define SPRN_HFSCR 0xbe /* HV=1 Facility Status & Control Register */
+#define HFSCR_PREFIX __MASK(FSCR_PREFIX_LG)
#define HFSCR_MSGP __MASK(FSCR_MSGP_LG)
#define HFSCR_TAR __MASK(FSCR_TAR_LG)
#define HFSCR_EBB __MASK(FSCR_EBB_LG)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3fca22276bb1..493a3fa0ac1a 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1720,6 +1720,7 @@ void facility_unavailable_exception(struct pt_regs *regs)
[FSCR_TAR_LG] = "TAR",
[FSCR_MSGP_LG] = "MSGP",
[FSCR_SCV_LG] = "SCV",
+ [FSCR_PREFIX_LG] = "PREFIX",
};
char *facility = "unknown";
u64 value;
--
2.17.1
^ permalink raw reply related
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