Re: [PATCH] powerpc/asm/cacheflush: Cleanup cacheflush function params
I've realised that changing the arguments for the cacheflush functions is much more work than its worth, due to other archs using these functions. The next patch will just translate the asm cacheflush functions to c, keeping the existing parameters. So this won't have any effect on the drivers. Thanks, Matt Brown On Thu, Jul 20, 2017 at 11:01 PM, Michael Ellermanwrote: > Geert Uytterhoeven writes: > >> On Thu, Jul 20, 2017 at 1:43 PM, Michael Ellerman >> wrote: >>> Matt Brown writes: The cacheflush prototypes currently use start and stop values and each call requires typecasting the address to an unsigned long. This patch changes the cacheflush prototypes to follow the x86 style of using a base and size values, with base being a void pointer. All callers of the cacheflush functions, including drivers, have been modified to conform to the new prototypes. The 64 bit cacheflush functions which were implemented in assembly code (flush_dcache_range, flush_inval_dcache_range) have been translated into C for readability and coherence. >> --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -51,13 +51,13 @@ static inline void __flush_dcache_icache_phys(unsigned long physaddr) * Write any modified data cache blocks out to memory and invalidate them. * Does not invalidate the corresponding instruction cache blocks. */ -static inline void flush_dcache_range(unsigned long start, unsigned long stop) +static inline void flush_dcache_range(void *start, unsigned long size) { - void *addr = (void *)(start & ~(L1_CACHE_BYTES - 1)); - unsigned long size = stop - (unsigned long)addr + (L1_CACHE_BYTES - 1); + void *addr = (void *)((u32)start & ~(L1_CACHE_BYTES - 1)); >>> >>> unsigned long would be nicer than u32. >> >> Indeed. That would make this work on ppc64, too. >> After which ppc64 has an identical copy (u64 = unsigned long on ppc64) below? > > That was Matt's homework to notice that ;) > > cheers
[PATCH 3/6] powerpc/mm: Ensure cpumask update is ordered
There is no guarantee that the various isync's involved with the context switch will order the update of the CPU mask with the first TLB entry for the new context being loaded by the HW. Be safe here and add a memory barrier to order any subsequent load/store which may bring entries into the TLB. The corresponding barrier on the other side already exists as pte updates use pte_xchg() which uses __cmpxchg_u64 which has a sync after the atomic operation. Signed-off-by: Benjamin Herrenschmidt--- arch/powerpc/include/asm/mmu_context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index ed9a36ee3107..ff1aeb2cd19f 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -110,6 +110,7 @@ static inline void switch_mm_irqs_off(struct mm_struct *prev, /* Mark this context has been used on the new CPU */ if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(next))) { cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); + smp_mb(); new_on_cpu = true; } -- 2.13.3
[PATCH 5/6] powerpc/mm: Optimize detection of thread local mm's
Instead of comparing the whole CPU mask every time, let's keep a counter of how many bits are set in the mask. Thus testing for a local mm only requires testing if that counter is 1 and the current CPU bit is set in the mask. Signed-off-by: Benjamin Herrenschmidt--- arch/powerpc/include/asm/book3s/64/mmu.h | 3 +++ arch/powerpc/include/asm/mmu_context.h | 9 + arch/powerpc/include/asm/tlb.h | 11 ++- arch/powerpc/mm/mmu_context_book3s64.c | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 1a220cdff923..c3b00e8ff791 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -83,6 +83,9 @@ typedef struct { mm_context_id_t id; u16 user_psize; /* page size index */ + /* Number of bits in the mm_cpumask */ + atomic_t active_cpus; + /* NPU NMMU context */ struct npu_context *npu_context; diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index ff1aeb2cd19f..cf8f50cd4030 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -96,6 +96,14 @@ static inline void switch_mm_pgdir(struct task_struct *tsk, struct mm_struct *mm) { } #endif +#ifdef CONFIG_PPC_BOOK3S_64 +static inline void inc_mm_active_cpus(struct mm_struct *mm) +{ + atomic_inc(>context.active_cpus); +} +#else +static inline void inc_mm_active_cpus(struct mm_struct *mm) { } +#endif /* * switch_mm is the entry point called from the architecture independent @@ -110,6 +118,7 @@ static inline void switch_mm_irqs_off(struct mm_struct *prev, /* Mark this context has been used on the new CPU */ if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(next))) { cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); + inc_mm_active_cpus(next); smp_mb(); new_on_cpu = true; } diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h index 609557569f65..a7eabff27a0f 100644 --- a/arch/powerpc/include/asm/tlb.h +++ b/arch/powerpc/include/asm/tlb.h @@ -69,13 +69,22 @@ static inline int mm_is_core_local(struct mm_struct *mm) topology_sibling_cpumask(smp_processor_id())); } +#ifdef CONFIG_PPC_BOOK3S_64 +static inline int mm_is_thread_local(struct mm_struct *mm) +{ + if (atomic_read(>context.active_cpus) > 1) + return false; + return cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)); +} +#else /* CONFIG_PPC_BOOK3S_64 */ static inline int mm_is_thread_local(struct mm_struct *mm) { return cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())); } +#endif /* !CONFIG_PPC_BOOK3S_64 */ -#else +#else /* CONFIG_SMP */ static inline int mm_is_core_local(struct mm_struct *mm) { return 1; diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index 8159f5219137..de17d3e714aa 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c @@ -174,6 +174,8 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) #ifdef CONFIG_SPAPR_TCE_IOMMU mm_iommu_init(mm); #endif + atomic_set(>context.active_cpus, 0); + return 0; } -- 2.13.3
[PATCH 1/6] powerpc/mm: Move pgdir setting into a helper
Makes switch_mm_irqs_off() a bit more readable Signed-off-by: Benjamin Herrenschmidt--- arch/powerpc/include/asm/mmu_context.h | 30 ++ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 94d93f256b94..603b0e5cdec0 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -77,6 +77,26 @@ extern void switch_cop(struct mm_struct *next); extern int use_cop(unsigned long acop, struct mm_struct *mm); extern void drop_cop(unsigned long acop, struct mm_struct *mm); +#if defined(CONFIG_PPC32) +static inline void switch_mm_pgdir(struct task_struct *tsk, + struct mm_struct *mm) +{ + /* 32-bit keeps track of the current PGDIR in the thread struct */ + tsk->thread.pgdir = mm->pgd; +} +#elif defined(CONFIG_PPC_BOOK3E_64) +static inline void switch_mm_pgdir(struct task_struct *tsk, + struct mm_struct *mm) +{ + /* 64-bit Book3E keeps track of current PGD in the PACA */ + get_paca()->pgd = mm->pgd; +} +#else +static inline void switch_mm_pgdir(struct task_struct *tsk, + struct mm_struct *mm) { } +#endif + + /* * switch_mm is the entry point called from the architecture independent * code in kernel/sched/core.c @@ -93,15 +113,9 @@ static inline void switch_mm_irqs_off(struct mm_struct *prev, new_on_cpu = true; } - /* 32-bit keeps track of the current PGDIR in the thread struct */ -#ifdef CONFIG_PPC32 - tsk->thread.pgdir = next->pgd; -#endif /* CONFIG_PPC32 */ + /* Some subarchs need to track the PGD elsewhere */ + switch_mm_pgdir(tsk, next); - /* 64-bit Book3E keeps track of current PGD in the PACA */ -#ifdef CONFIG_PPC_BOOK3E_64 - get_paca()->pgd = next->pgd; -#endif /* Nothing else to do if we aren't actually switching */ if (prev == next) return; -- 2.13.3
[PATCH 2/6] powerpc/mm: Avoid double irq save/restore in activate_mm
It calls switch_mm() which already does the irq save/restore these days. Signed-off-by: Benjamin Herrenschmidt--- arch/powerpc/include/asm/mmu_context.h | 4 1 file changed, 4 deletions(-) diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 603b0e5cdec0..ed9a36ee3107 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -158,11 +158,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, */ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { - unsigned long flags; - - local_irq_save(flags); switch_mm(prev, next, current); - local_irq_restore(flags); } /* We don't currently use enter_lazy_tlb() for anything */ -- 2.13.3
[PATCH 4/6] powerpc/mm: Use mm_is_thread_local() instread of open-coding
We open-code testing for the mm being local to the current CPU in a few places. Use our existing helper instead. Signed-off-by: Benjamin Herrenschmidt--- arch/powerpc/mm/hash_utils_64.c | 6 ++ arch/powerpc/mm/hugetlbpage.c| 3 +-- arch/powerpc/mm/pgtable-hash64.c | 4 +--- arch/powerpc/mm/tlb_hash64.c | 7 ++- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 7a20669c19e7..943d9fe2b9a3 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -1228,7 +1228,6 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long vsid; pte_t *ptep; unsigned hugeshift; - const struct cpumask *tmp; int rc, user_region = 0; int psize, ssize; @@ -1280,8 +1279,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea, } /* Check CPU locality */ - tmp = cpumask_of(smp_processor_id()); - if (user_region && cpumask_equal(mm_cpumask(mm), tmp)) + if (user_region && mm_is_thread_local(mm)) flags |= HPTE_LOCAL_UPDATE; #ifndef CONFIG_PPC_64K_PAGES @@ -1543,7 +1541,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, #endif /* CONFIG_PPC_64K_PAGES */ /* Is that local to this CPU ? */ - if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id( + if (mm_is_thread_local(mm)) update_flags |= HPTE_LOCAL_UPDATE; /* Hash it in */ diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index e1bf5ca397fe..122844c0734a 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -407,8 +407,7 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte) batchp = _cpu_var(hugepd_freelist_cur); if (atomic_read(>mm->mm_users) < 2 || - cpumask_equal(mm_cpumask(tlb->mm), - cpumask_of(smp_processor_id( { + mm_is_thread_local(tlb->mm)) { kmem_cache_free(hugepte_cache, hugepte); put_cpu_var(hugepd_freelist_cur); return; diff --git a/arch/powerpc/mm/pgtable-hash64.c b/arch/powerpc/mm/pgtable-hash64.c index 443a2c66a304..d89c637cb600 100644 --- a/arch/powerpc/mm/pgtable-hash64.c +++ b/arch/powerpc/mm/pgtable-hash64.c @@ -329,7 +329,6 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, unsigned int psize; unsigned long vsid; unsigned long flags = 0; - const struct cpumask *tmp; /* get the base page size,vsid and segment size */ #ifdef CONFIG_DEBUG_VM @@ -350,8 +349,7 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, ssize = mmu_kernel_ssize; } - tmp = cpumask_of(smp_processor_id()); - if (cpumask_equal(mm_cpumask(mm), tmp)) + if (mm_is_thread_local(mm)) flags |= HPTE_LOCAL_UPDATE; return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, flags); diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index b5b0fb97b9c0..4dde13d7452d 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -138,13 +138,10 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr, */ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) { - const struct cpumask *tmp; - int i, local = 0; + int i, local; i = batch->index; - tmp = cpumask_of(smp_processor_id()); - if (cpumask_equal(mm_cpumask(batch->mm), tmp)) - local = 1; + local = mm_is_thread_local(batch->mm); if (i == 1) flush_hash_page(batch->vpn[0], batch->pte[0], batch->psize, batch->ssize, local); -- 2.13.3
[PATCH 6/6] powerpc/mm: Make switch_mm_irqs_off() out of line
It's too big to be inline, there is no reason to keep it that way. Signed-off-by: Benjamin Herrenschmidt# Conflicts: # arch/powerpc/include/asm/mmu_context.h --- arch/powerpc/include/asm/mmu_context.h | 73 ++ arch/powerpc/mm/Makefile | 2 +- arch/powerpc/mm/mmu_context.c | 81 ++ 3 files changed, 85 insertions(+), 71 deletions(-) create mode 100644 arch/powerpc/mm/mmu_context.c diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index cf8f50cd4030..ed949b2675cb 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -77,76 +77,9 @@ extern void switch_cop(struct mm_struct *next); extern int use_cop(unsigned long acop, struct mm_struct *mm); extern void drop_cop(unsigned long acop, struct mm_struct *mm); -#if defined(CONFIG_PPC32) -static inline void switch_mm_pgdir(struct task_struct *tsk, - struct mm_struct *mm) -{ - /* 32-bit keeps track of the current PGDIR in the thread struct */ - tsk->thread.pgdir = mm->pgd; -} -#elif defined(CONFIG_PPC_BOOK3E_64) -static inline void switch_mm_pgdir(struct task_struct *tsk, - struct mm_struct *mm) -{ - /* 64-bit Book3E keeps track of current PGD in the PACA */ - get_paca()->pgd = mm->pgd; -} -#else -static inline void switch_mm_pgdir(struct task_struct *tsk, - struct mm_struct *mm) { } -#endif - -#ifdef CONFIG_PPC_BOOK3S_64 -static inline void inc_mm_active_cpus(struct mm_struct *mm) -{ - atomic_inc(>context.active_cpus); -} -#else -static inline void inc_mm_active_cpus(struct mm_struct *mm) { } -#endif - -/* - * switch_mm is the entry point called from the architecture independent - * code in kernel/sched/core.c - */ -static inline void switch_mm_irqs_off(struct mm_struct *prev, - struct mm_struct *next, - struct task_struct *tsk) -{ - bool new_on_cpu = false; - - /* Mark this context has been used on the new CPU */ - if (!cpumask_test_cpu(smp_processor_id(), mm_cpumask(next))) { - cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); - inc_mm_active_cpus(next); - smp_mb(); - new_on_cpu = true; - } - - /* Some subarchs need to track the PGD elsewhere */ - switch_mm_pgdir(tsk, next); - - /* Nothing else to do if we aren't actually switching */ - if (prev == next) - return; - - /* We must stop all altivec streams before changing the HW -* context -*/ -#ifdef CONFIG_ALTIVEC - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - asm volatile ("dssall"); -#endif /* CONFIG_ALTIVEC */ - - if (new_on_cpu) - radix_kvm_prefetch_workaround(next); - - /* -* The actual HW switching method differs between the various -* sub architectures. Out of line for now -*/ - switch_mmu_context(prev, next, tsk); -} +extern void switch_mm_irqs_off(struct mm_struct *prev, + struct mm_struct *next, + struct task_struct *tsk); static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index fa6a6ba34355..fb844d2f266e 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -8,7 +8,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) obj-y := fault.o mem.o pgtable.o mmap.o \ init_$(BITS).o pgtable_$(BITS).o \ - init-common.o + init-common.o mmu_context.o obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ tlb_nohash_low.o obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o diff --git a/arch/powerpc/mm/mmu_context.c b/arch/powerpc/mm/mmu_context.c new file mode 100644 index ..5f7b59c7ace5 --- /dev/null +++ b/arch/powerpc/mm/mmu_context.c @@ -0,0 +1,81 @@ +/* + * Common implementation of switch_mm_irqs_off + * + * Copyright IBM Corp. 2017 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include + +#include + +#if defined(CONFIG_PPC32) +static inline void switch_mm_pgdir(struct task_struct *tsk, + struct mm_struct *mm) +{ + /* 32-bit keeps track of the current PGDIR in the thread struct */ + tsk->thread.pgdir =
[PATCH v5] powerpc/mm/radix: Workaround prefetch issue with KVM
There's a somewhat architectural issue with Radix MMU and KVM. When coming out of a guest with AIL (ie, MMU enabled), we start executing hypervisor code with the PID register still containing whatever the guest has been using. The problem is that the CPU can (and will) then start prefetching or speculatively load from whatever host context has that same PID (if any), thus bringing translations for that context into the TLB, which Linux doesn't know about. This can cause stale translations and subsequent crashes. Fixing this in a way that is neither racy nor a huge performance impact is difficult. We could just make the host invalidations always use broadcast forms but that would hurt single threaded programs for example. We chose to fix it instead by partitioning the PID space between guest and host. This is possible because today Linux only use 19 out of the 20 bits of PID space, so existing guests will work if we make the host use the top half of the 20 bits space. We additionally add a property to indicate to Linux the size of the PID register which will be useful if we eventually have processors with a larger PID space available. There is still an issue with malicious guests purposefully setting the PID register to a value in the host range. Hopefully future HW can prevent that, but in the meantime, we handle it with a pair of kludges: - On the way out of a guest, before we clear the current VCPU in the PACA, we check the PID and if it's outside of the permitted range we flush the TLB for that PID. - When context switching, if the mm is "new" on that CPU (the corresponding bit was set for the first time in the mm cpumask), we check if any sibling thread is in KVM (has a non-NULL VCPU pointer in the PACA). If that is the case, we also flush the PID for that CPU (core). This second part is needed to handle the case where a process is migrated (or starts a new pthread) on a sibling thread of the CPU coming out of KVM, as there's a window where stale translations can exist before we detect it and flush them out. A future optimization could be added by keeping track of whether the PID has ever been used and avoid doing that for completely fresh PIDs. We could similarily mark PIDs that have been the subject of a global invalidation as "fresh". But for now this will do. Signed-off-by: Benjamin Herrenschmidt--- v2. Do the check on KVM exit *after* we've restored the host PID v3. Properly check for radix in the exit assembly and avoid adding yet another function to tlb-radix.c v4. Don't add an argument to switch_mmu_context(), instead call a workaround function directly from switch_mm_irqs_off(), which keeps the patch a lot smaller. v5. Change LPIDR to 0 before doing the tlbiel loop --- arch/powerpc/include/asm/book3s/64/mmu.h | 15 arch/powerpc/include/asm/mmu_context.h | 18 -- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 59 +++- arch/powerpc/mm/mmu_context_book3s64.c | 9 +++-- arch/powerpc/mm/pgtable-radix.c | 34 +- arch/powerpc/mm/tlb-radix.c | 45 ++-- 6 files changed, 158 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 77529a3e3811..5b4023c616f7 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -59,13 +59,14 @@ extern struct patb_entry *partition_tb; #define PRTS_MASK 0x1f/* process table size field */ #define PRTB_MASK 0x0000UL -/* - * Limit process table to PAGE_SIZE table. This - * also limit the max pid we can support. - * MAX_USER_CONTEXT * 16 bytes of space. - */ -#define PRTB_SIZE_SHIFT(CONTEXT_BITS + 4) -#define PRTB_ENTRIES (1ul << CONTEXT_BITS) +/* Number of supported PID bits */ +extern unsigned int mmu_pid_bits; + +/* Base PID to allocate from */ +extern unsigned int mmu_base_pid; + +#define PRTB_SIZE_SHIFT(mmu_pid_bits + 4) +#define PRTB_ENTRIES (1ul << mmu_pid_bits) /* * Power9 currently only support 64K partition table size. diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index da7e9432fa8f..0c76675394c5 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -45,7 +45,7 @@ extern void set_context(unsigned long id, pgd_t *pgd); #ifdef CONFIG_PPC_BOOK3S_64 extern void radix__switch_mmu_context(struct mm_struct *prev, -struct mm_struct *next); + struct mm_struct *next); static inline void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) @@ -67,6 +67,12 @@ extern void __destroy_context(unsigned long context_id); extern void
[PATCH v2] qe: fix compile issue for arm64
Signed-off-by: Zhao Qiang--- Changes for v2: - include all Errata QE_General4 in #ifdef drivers/soc/fsl/qe/qe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index 2ef6fc6..4ac9ce8 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -229,9 +229,11 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier) /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says that the BRG divisor must be even if you're not using divide-by-16 mode. */ +#ifdef CONFIG_PPC if (pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x)) if (!div16 && (divisor & 1) && (divisor > 3)) divisor++; +#endif tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE | div16; -- 2.1.0.27.g96db324
Re: [PATCH] qe: fix compile issue for arm64
On Mon, 2017-07-24 at 02:09 +, Qiang Zhao wrote: > On Fri, 2017-07-21 at 02:34PM, Michael Ellermanwrote: > > > -Original Message- > > From: Michael Ellerman [mailto:m...@ellerman.id.au] > > Sent: Friday, July 21, 2017 2:34 PM > > To: Qiang Zhao ; o...@buserror.net > > Cc: valentin.longch...@keymile.com; linuxppc-dev@lists.ozlabs.org; linux- > > ker...@vger.kernel.org; Qiang Zhao > > Subject: Re: [PATCH] qe: fix compile issue for arm64 > > > > Zhao Qiang writes: > > > > > Signed-off-by: Zhao Qiang > > > --- > > > drivers/soc/fsl/qe/qe.c | 2 ++ > > > 1 file changed, 2 insertions(+) > > > > > > diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index > > > 2ef6fc6..d48fa4a 100644 > > > --- a/drivers/soc/fsl/qe/qe.c > > > +++ b/drivers/soc/fsl/qe/qe.c > > > @@ -229,7 +229,9 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, > > > > unsigned int multiplier) > > > /* Errata QE_General4, which affects some MPC832x and MPC836x > > > > SOCs, says > > > that the BRG divisor must be even if you're not using > > > divide-by-16 > > > mode. */ > > > +#ifdef CONFIG_PPC > > > if (pvr_version_is(PVR_VER_836x) || > > > pvr_version_is(PVR_VER_832x) > > > +#endif > > > if (!div16 && (divisor & 1) && (divisor > 3)) > > > divisor++; > > > > Are you sure that's what you want to do on arm64 ? > > Is there any problem? > > Best Regards > Qiang Zhao The comment says the workaround applies to MPC832x and MPC836x, but you're applying the workaround on arm64 as well. -Scott
RE: [PATCH 1/2] fsl/qe: NULL dereference on error in ucc_of_parse_tdm()
On Sat 7/22/2017 3:34 PM, Dan Carpenterwrote: > -Original Message- > From: Dan Carpenter [mailto:dan.carpen...@oracle.com] > Sent: Saturday, July 22, 2017 3:34 PM > To: Qiang Zhao > Cc: Leo Li ; linuxppc-dev@lists.ozlabs.org; kernel- > janit...@vger.kernel.org > Subject: [PATCH 1/2] fsl/qe: NULL dereference on error in ucc_of_parse_tdm() > > If "pdev = of_find_device_by_node(np2);" fails then it would lead to a NULL > dereference. This function is called from probe() and we're using managed > resources so we can just return without doing a manual cleanup. You mean it will be cleaned up automatically? > > Fixes: 35ef1c20fdb2 ("fsl/qe: Add QE TDM lib") > Signed-off-by: Dan Carpenter Best Regards Qiang Zhao
RE: [PATCH] qe: fix compile issue for arm64
On Fri, 2017-07-21 at 02:34PM, Michael Ellermanwrote: > -Original Message- > From: Michael Ellerman [mailto:m...@ellerman.id.au] > Sent: Friday, July 21, 2017 2:34 PM > To: Qiang Zhao ; o...@buserror.net > Cc: valentin.longch...@keymile.com; linuxppc-dev@lists.ozlabs.org; linux- > ker...@vger.kernel.org; Qiang Zhao > Subject: Re: [PATCH] qe: fix compile issue for arm64 > > Zhao Qiang writes: > > > Signed-off-by: Zhao Qiang > > --- > > drivers/soc/fsl/qe/qe.c | 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index > > 2ef6fc6..d48fa4a 100644 > > --- a/drivers/soc/fsl/qe/qe.c > > +++ b/drivers/soc/fsl/qe/qe.c > > @@ -229,7 +229,9 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, > unsigned int multiplier) > > /* Errata QE_General4, which affects some MPC832x and MPC836x > SOCs, says > >that the BRG divisor must be even if you're not using divide-by-16 > >mode. */ > > +#ifdef CONFIG_PPC > > if (pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x) > > +#endif > > if (!div16 && (divisor & 1) && (divisor > 3)) > > divisor++; > > Are you sure that's what you want to do on arm64 ? Is there any problem? Best Regards Qiang Zhao
Re: [PATCH] powerpc/tm: fix TM SPRs in code dump file
On Wed, 2017-07-19 at 01:44 -0400, Gustavo Romero wrote: > Currently flush_tmregs_to_thread() does not update accordingly the thread > structures from live state before a core dump rendering wrong values of > THFAR, TFIAR, and TEXASR in core dump files. > > That commit fixes it by copying from live state to the appropriate thread > structures when it's necessary. > > Signed-off-by: Gustavo RomeroGustavo was nice enough to provide me with a simple test case: int main(void) { __builtin_set_texasr(0x4841434b); __builtin_set_tfhar(0xbfee00); __builtin_set_tfiar(0x4841434b); asm volatile (".long 0x0"); return 0; } Running this binary in a loop and inspecting the resulting core file with a modified elfutils also provided by Gustavo (https://sourceware.o rg/ml/elfutils-devel/2017-q3/msg00030.html) should always observe the values that those __builtin functions set. __builtin_set_{texasr,tfhar,tfiar} are just wrappers around the corresponding mtspr instruction. On an unmodified 4.13-rc1 it takes in the order of 10 executions of the test to observe an incorrect TM SPR values in the core file (typically zero). The above test was run on the same 4.13-rc1 with this patch applied for a over 48 hours. The test was executed at a rate of about one run per second. An incorrect value was never observed. This gives me confidence that this patch is correct. Running the kernel selftests does not detect any regressions. Reviewed-by: Cyril Bur > --- > arch/powerpc/kernel/ptrace.c | 13 ++--- > 1 file changed, 10 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c > index 925a4ef..660ed39 100644 > --- a/arch/powerpc/kernel/ptrace.c > +++ b/arch/powerpc/kernel/ptrace.c > @@ -127,12 +127,19 @@ static void flush_tmregs_to_thread(struct task_struct > *tsk) >* If task is not current, it will have been flushed already to >* it's thread_struct during __switch_to(). >* > - * A reclaim flushes ALL the state. > + * A reclaim flushes ALL the state or if not in TM save TM SPRs > + * in the appropriate thread structures from live. >*/ > > - if (tsk == current && MSR_TM_SUSPENDED(mfmsr())) > - tm_reclaim_current(TM_CAUSE_SIGNAL); > + if (tsk != current) > + return; > > + if (MSR_TM_SUSPENDED(mfmsr())) { > + tm_reclaim_current(TM_CAUSE_SIGNAL); > + } else { > + tm_enable(); > + tm_save_sprs(&(tsk->thread)); > + } > } > #else > static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
[PATCH v2 5/5] powerpc/lib/sstep: Add isel instruction emulation
This adds emulation for the isel instruction. Tested for correctness against the isel instruction and its extended mnemonics (lt, gt, eq) on ppc64le. Signed-off-by: Matt Brown--- v2: - fixed opcode - fixed definition to include the 'if RA=0, a=0' clause - fixed ccr bitshifting error --- arch/powerpc/lib/sstep.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index b08eb96..e1f4ec6 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1246,6 +1246,17 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, /* * Logical instructions */ + case 15:/* isel */ + mb = (instr >> 6) & 0x1f; /* bc */ + val = (regs->ccr >> (31 - mb)) & 1; + val2 = (ra) ? regs->gpr[ra] : 0; + + if (val) + regs->gpr[rd] = val2; + else + regs->gpr[rd] = regs->gpr[rb]; + goto logical_done; + case 26:/* cntlzw */ asm("cntlzw %0,%1" : "=r" (regs->gpr[ra]) : "r" (regs->gpr[rd])); -- 2.9.3
[PATCH 4/5] powerpc/lib/sstep: Add prty instruction emulation
This add emulation for the prtyw and prtyd instructions. Tested for logical correctness against the prtyw and prtyd instructions on ppc64le. Signed-off-by: Matt Brown--- v2: - fixed opcodes - fixed bitshifting and typecast errors - merged do_prtyw and do_prtyd into single function --- arch/powerpc/lib/sstep.c | 31 +++ 1 file changed, 31 insertions(+) diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index a756f44..1820fd6 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -658,6 +658,29 @@ static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1, regs->gpr[ra] = perm; } #endif /* __powerpc64__ */ +/* + * The size parameter adjusts the equivalent prty instruction. + * prtyw = 32, prtyd = 64 + */ +static nokprobe_inline void do_prty(struct pt_regs *regs, unsigned long v, + int size, int ra) +{ + unsigned long long high, low; + unsigned int i; + + high = 0; + low = 0; + + for (i = 0; i < 8; i++) { + if (v & (1UL << (i * 8))) + (i < 4) ? (low++) : (high++); + } + + if (size == 32) + regs->gpr[ra] = ((high & 1) << 32) | (low & 1); + else + regs->gpr[ra] = (high + low) & 1; +} static nokprobe_inline int trap_compare(long v1, long v2) { @@ -1248,6 +1271,14 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, case 124: /* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; + + case 154: /* prtyw */ + do_prty(regs, regs->gpr[rd], 32, ra); + goto logical_done; + + case 186: /* prtyd */ + do_prty(regs, regs->gpr[rd], 64, ra); + goto logical_done; #ifdef __powerpc64__ case 252: /* bpermd */ do_bpermd(regs, regs->gpr[rd], regs->gpr[rb], ra); -- 2.9.3
[PATCH v2 3/5] powerpc/lib/sstep: Add bpermd instruction emulation
This adds emulation for the bpermd instruction. Tested for correctness against the bpermd instruction on ppc64le. Signed-off-by: Matt Brown--- v2: - fixed opcode - added ifdef tags to do_bpermd func - fixed bitshifting errors --- arch/powerpc/lib/sstep.c | 24 +++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index e6a16a3..a756f44 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -641,6 +641,24 @@ static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1, regs->gpr[ra] = (high << 32) | low; } +#ifdef __powerpc64__ +static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1, + unsigned long v2, int ra) +{ + unsigned char perm, idx; + unsigned int i; + + perm = 0; + for (i = 0; i < 8; i++) { + idx = (v1 >> (i * 8)) & 0xff; + if (idx < 64) + if (v2 & PPC_BIT(idx)) + perm |= 1 << i; + } + regs->gpr[ra] = perm; +} +#endif /* __powerpc64__ */ + static nokprobe_inline int trap_compare(long v1, long v2) { int ret = 0; @@ -1230,7 +1248,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, case 124: /* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; - +#ifdef __powerpc64__ + case 252: /* bpermd */ + do_bpermd(regs, regs->gpr[rd], regs->gpr[rb], ra); + goto logical_done; +#endif case 284: /* xor */ regs->gpr[ra] = ~(regs->gpr[rd] ^ regs->gpr[rb]); goto logical_done; -- 2.9.3
[PATCH v2 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
This adds emulations for the popcntb, popcntw, and popcntd instructions. Tested for correctness against the popcnt{b,w,d} instructions on ppc64le. Signed-off-by: Matt Brown--- v2: - fixed opcodes - fixed typecasting - fixed bitshifting error for both 32 and 64bit arch --- arch/powerpc/lib/sstep.c | 43 ++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 87d277f..e6a16a3 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -612,6 +612,35 @@ static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1, regs->gpr[rd] = out_val; } +/* + * The size parameter is used to adjust the equivalent popcnt instruction. + * popcntb = 8, popcntw = 32, popcntd = 64 + */ +static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1, + int size, int ra) +{ + unsigned long long high, low, mask; + unsigned int n; + int i, j; + + high = 0; + low = 0; + + for (i = 0; i < (64 / size); i++) { + n = 0; + for (j = 0; j < size; j++) { + mask = 1UL << (j + (i * size)); + if (v1 & mask) + n++; + } + if ((i * size) < 32) + low |= n << (i * size); + else + high |= n << ((i * size) - 32); + } + regs->gpr[ra] = (high << 32) | low; +} + static nokprobe_inline int trap_compare(long v1, long v2) { int ret = 0; @@ -1194,6 +1223,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, regs->gpr[ra] = regs->gpr[rd] & ~regs->gpr[rb]; goto logical_done; + case 122: /* popcntb */ + do_popcnt(regs, regs->gpr[rd], 8, ra); + goto logical_done; + case 124: /* nor */ regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]); goto logical_done; @@ -1206,6 +1239,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, regs->gpr[ra] = regs->gpr[rd] ^ regs->gpr[rb]; goto logical_done; + case 378: /* popcntw */ + do_popcnt(regs, regs->gpr[rd], 32, ra); + goto logical_done; + case 412: /* orc */ regs->gpr[ra] = regs->gpr[rd] | ~regs->gpr[rb]; goto logical_done; @@ -1217,7 +1254,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, case 476: /* nand */ regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]); goto logical_done; - +#ifdef __powerpc64__ + case 506: /* popcntd */ + do_popcnt(regs, regs->gpr[rd], 64, ra); + goto logical_done; +#endif case 922: /* extsh */ regs->gpr[ra] = (signed short) regs->gpr[rd]; goto logical_done; -- 2.9.3
[PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation
This patch adds emulation of the cmpb instruction, enabling xmon to emulate this instruction. Tested for correctness against the cmpb asm instruction on ppc64le. Signed-off-by: Matt Brown--- v2: - fixed opcode - fixed mask typecasting --- 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 33117f8..87d277f 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -596,6 +596,22 @@ static nokprobe_inline void do_cmp_unsigned(struct pt_regs *regs, unsigned long regs->ccr = (regs->ccr & ~(0xf << shift)) | (crval << shift); } +static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1, + unsigned long v2, int rd) +{ + unsigned long long out_val, mask; + int i; + + out_val = 0; + for (i = 0; i < 8; i++) { + mask = 0xffUL << (i * 8); + if ((v1 & mask) == (v2 & mask)) + out_val |= mask; + } + + regs->gpr[rd] = out_val; +} + static nokprobe_inline int trap_compare(long v1, long v2) { int ret = 0; @@ -1049,6 +1065,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs, do_cmp_unsigned(regs, val, val2, rd >> 2); goto instr_done; + case 508: /* cmpb */ + do_cmpb(regs, regs->gpr[rd], regs->gpr[rb], ra); + goto instr_done; + /* * Arithmetic instructions */ -- 2.9.3
Re: [PATCH] powerpc/pseries: Fix of_node_put() underflow during pseries remove
On Fri, Jul 21, 2017 at 04:51:39PM +0200, Laurent Vivier wrote: > As for commit 68baf692c435 ("powerpc/pseries: Fix of_node_put() > underflow during DLPAR remove"), the call to of_node_put() > must be removed from pSeries_reconfig_remove_node(). > > dlpar_detach_node() and pSeries_reconfig_remove_node() call > of_detach_node(), and thus the node should not be released > in this case too. > > Signed-off-by: Laurent VivierReviewed-by: David Gibson > --- > arch/powerpc/platforms/pseries/reconfig.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/arch/powerpc/platforms/pseries/reconfig.c > b/arch/powerpc/platforms/pseries/reconfig.c > index e5bf1e8..011ef21 100644 > --- a/arch/powerpc/platforms/pseries/reconfig.c > +++ b/arch/powerpc/platforms/pseries/reconfig.c > @@ -82,7 +82,6 @@ static int pSeries_reconfig_remove_node(struct device_node > *np) > > of_detach_node(np); > of_node_put(parent); > - of_node_put(np); /* Must decrement the refcount */ > return 0; > } > -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [PATCH 0/4] Allow non-legacy cards to be vgaarb default
Hi Ard, > But the fact remains that we are going about this the wrong way. > Whether a graphics card decodes legacy VGA ranges or not has *nothing* > to do with whether or not it is in fact the primary device on a > non-x86 system, and so I still think the VGA arbiter should be omitted > entirely for such platforms, and Xorg should be fixed instead. OK, I see where you're coming from. I've been trying to keep my changes small as I don't want to end up on the hook for the almost limitless range of problems that changing this sort of code can have, but I do take your point that it's a bit of an ugly hack of a solution. Say we were to change Xorg instead. What would correct Xorg behaviour look like? Xorg would need to honour the boot_vga file if it existed so as not to break x86, etc. So your proposed Xorg - if it couldn't find a default card that way, and if there was no helpful config file info, would arbitrarily pick a card that has an Xorg driver? In other words, much like the proposed kernel approach but at a different level of the stack? Are there other graphical applications we care about (other than Xorg) that would need to be patched? I'm happy to do the Xorg patch, but I don't know if anything other than Xorg keys off the boot_vga file. I'm not fundamentally opposed to this approach if the Xorg community is happy with it, the kernel community is happy with it, and no-one expects me to provide patches to any other user-space applications that depend on boot_vga. Regards, Daniel
Re: [PATCH] powerpc/vdso64: Add support for CLOCK_{REALTIME/MONOTONIC}_COARSE
Hi Santosh, [auto build test ERROR on powerpc/next] [also build test ERROR on v4.13-rc1 next-20170721] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Santosh-Sivaraj/powerpc-vdso64-Add-support-for-CLOCK_-REALTIME-MONOTONIC-_COARSE/20170722-235025 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc-ps3_defconfig (attached as .config) compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=powerpc All errors (new ones prefixed by >>): arch/powerpc/kernel/vdso64/gettime.o: In function `kernel_clock_gettime': >> arch/powerpc/kernel/vdso64/gettime.c:134: undefined reference to >> `.__get_datapage' collect2: error: ld returned 1 exit status vim +134 arch/powerpc/kernel/vdso64/gettime.c 130 131 notrace int kernel_clock_gettime(clockid_t clk_id, struct timespec *tp) 132 { 133 int ret; > 134 struct vdso_data *vdata = __get_datapage(); --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH 1/2] powerpc/xmon: support dumping software pagetables
Hi Balbir, [auto build test ERROR on powerpc/next] [also build test ERROR on v4.13-rc1 next-20170721] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Balbir-Singh/powerpc-xmon-support-dumping-software-pagetables/20170723-002848 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc-akebono_defconfig (attached as .config) compiler: powerpc-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705 reproduce: wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=powerpc All errors (new ones prefixed by >>): arch/powerpc/xmon/xmon.c: In function 'show_pte': >> arch/powerpc/xmon/xmon.c:2929:6: error: implicit declaration of function >> 'pud_huge' [-Werror=implicit-function-declaration] if (pud_huge(*pudp)) { ^~~~ >> arch/powerpc/xmon/xmon.c:2942:6: error: implicit declaration of function >> 'pmd_huge' [-Werror=implicit-function-declaration] if (pmd_huge(*pmdp)) { ^~~~ cc1: all warnings being treated as errors vim +/pud_huge +2929 arch/powerpc/xmon/xmon.c 2874 2875 static void show_pte(unsigned long tskv) 2876 { 2877 unsigned long addr = 0; 2878 struct task_struct *tsk = NULL; 2879 struct mm_struct *mm; 2880 pgd_t *pgdp; 2881 pud_t *pudp; 2882 pmd_t *pmdp; 2883 pte_t *ptep; 2884 2885 tsk = (struct task_struct *)tskv; 2886 if (tsk == NULL) 2887 mm = _mm; 2888 else 2889 mm = tsk->active_mm; 2890 2891 if (mm == NULL) 2892 mm = _mm; 2893 2894 if (!scanhex()) 2895 printf("need address to translate\n"); 2896 2897 if (setjmp(bus_error_jmp) != 0) { 2898 catch_memory_errors = 0; 2899 printf("*** Error dumping pte for task %p\n", tsk); 2900 return; 2901 } 2902 2903 catch_memory_errors = 1; 2904 sync(); 2905 2906 if (mm == _mm) 2907 pgdp = pgd_offset_k(addr); 2908 else 2909 pgdp = pgd_offset(mm, addr); 2910 2911 if (pgd_none(*pgdp)) { 2912 printf("no linux page table for address\n"); 2913 return; 2914 } 2915 2916 if (pgd_huge(*pgdp)) { 2917 format_pte(pgd_val(*pgdp)); 2918 return; 2919 } 2920 printf("G: 0x%8lx\t", pgd_val(*pgdp)); 2921 2922 pudp = pud_offset(pgdp, addr); 2923 2924 if (pud_none(*pudp)) { 2925 printf("No valid PUD\n"); 2926 return; 2927 } 2928 > 2929 if (pud_huge(*pudp)) { 2930 format_pte(pud_val(*pudp)); 2931 return; 2932 } 2933 printf("U: 0x%8lx\t", pud_val(*pudp)); 2934 2935 pmdp = pmd_offset(pudp, addr); 2936 2937 if (pmd_none(*pmdp)) { 2938 printf("No valid PMD\n"); 2939 return; 2940 } 2941 > 2942 if (pmd_huge(*pmdp)) { 2943 format_pte(pmd_val(*pmdp)); 2944 return; 2945 } 2946 printf("M: 0x%8lx\t", pmd_val(*pmdp)); 2947 2948 /* pte_offset_map is the same as pte_offset_kernel */ 2949 ptep = pte_offset_kernel(pmdp, addr); 2950 if (pte_none(*ptep)) { 2951 printf("no valid PTE\n"); 2952 return; 2953 } 2954 2955 format_pte(pte_val(*ptep)); 2956 2957 sync(); 2958 __delay(200); 2959 catch_memory_errors = 0; 2960 } 2961 static void show_tasks(void) 2962 { 2963 unsigned long tskv; 2964 struct task_struct *tsk = NULL; 2965 2966 printf(" task_struct ->thread.kspPID PPID S P CMD\n"); 2967 2968 if (scanhex()) 2969 tsk = (struct task_struct *)tskv; 2970 2971 if (setjmp(bus_error_jmp) != 0) { 2972 catch_memory_errors = 0; 2973 printf("*** Error dumping task %p\n", tsk); 2974 return; 2975 } 2976 2977 catch_memory_errors = 1; 2978 sync(); 2979 2980 if (tsk) 2981 show_task(tsk); 2982 else 2983