Commit 2cfd716d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'powerpc-4.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull more powerpc updates from Michael Ellerman:
 "These were delayed for various reasons, so I let them sit in next a
  bit longer, rather than including them in my first pull request.

  Fixes:
   - Fix early access to cpu_spec relocation from Benjamin Herrenschmidt
   - Fix incorrect event codes in power9-event-list from Madhavan Srinivasan
   - Move register_process_table() out of ppc_md from Michael Ellerman

  Use jump_label use for [cpu|mmu]_has_feature():
   - Add mmu_early_init_devtree() from Michael Ellerman
   - Move disable_radix handling into mmu_early_init_devtree() from Michael Ellerman
   - Do hash device tree scanning earlier from Michael Ellerman
   - Do radix device tree scanning earlier from Michael Ellerman
   - Do feature patching before MMU init from Michael Ellerman
   - Check features don't change after patching from Michael Ellerman
   - Make MMU_FTR_RADIX a MMU family feature from Aneesh Kumar K.V
   - Convert mmu_has_feature() to returning bool from Michael Ellerman
   - Convert cpu_has_feature() to returning bool from Michael Ellerman
   - Define radix_enabled() in one place & use static inline from Michael Ellerman
   - Add early_[cpu|mmu]_has_feature() from Michael Ellerman
   - Convert early cpu/mmu feature check to use the new helpers from Aneesh Kumar K.V
   - jump_label: Make it possible for arches to invoke jump_label_init() earlier from Kevin Hao
   - Call jump_label_init() in apply_feature_fixups() from Aneesh Kumar K.V
   - Remove mfvtb() from Kevin Hao
   - Move cpu_has_feature() to a separate file from Kevin Hao
   - Add kconfig option to use jump labels for cpu/mmu_has_feature() from Michael Ellerman
   - Add option to use jump label for cpu_has_feature() from Kevin Hao
   - Add option to use jump label for mmu_has_feature() from Kevin Hao
   - Catch usage of cpu/mmu_has_feature() before jump label init from Aneesh Kumar K.V
   - Annotate jump label assembly from Michael Ellerman

  TLB flush enhancements from Aneesh Kumar K.V:
   - radix: Implement tlb mmu gather flush efficiently
   - Add helper for finding SLBE LLP encoding
   - Use hugetlb flush functions
   - Drop multiple definition of mm_is_core_local
   - radix: Add tlb flush of THP ptes
   - radix: Rename function and drop unused arg
   - radix/hugetlb: Add helper for finding page size
   - hugetlb: Add flush_hugetlb_tlb_range
   - remove flush_tlb_page_nohash

  Add new ptrace regsets from Anshuman Khandual and Simon Guo:
   - elf: Add powerpc specific core note sections
   - Add the function flush_tmregs_to_thread
   - Enable in transaction NT_PRFPREG ptrace requests
   - Enable in transaction NT_PPC_VMX ptrace requests
   - Enable in transaction NT_PPC_VSX ptrace requests
   - Adapt gpr32_get, gpr32_set functions for transaction
   - Enable support for NT_PPC_CGPR
   - Enable support for NT_PPC_CFPR
   - Enable support for NT_PPC_CVMX
   - Enable support for NT_PPC_CVSX
   - Enable support for TM SPR state
   - Enable NT_PPC_TM_CTAR, NT_PPC_TM_CPPR, NT_PPC_TM_CDSCR
   - Enable support for NT_PPPC_TAR, NT_PPC_PPR, NT_PPC_DSCR
   - Enable support for EBB registers
   - Enable support for Performance Monitor registers"

* tag 'powerpc-4.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (48 commits)
  powerpc/mm: Move register_process_table() out of ppc_md
  powerpc/perf: Fix incorrect event codes in power9-event-list
  powerpc/32: Fix early access to cpu_spec relocation
  powerpc/ptrace: Enable support for Performance Monitor registers
  powerpc/ptrace: Enable support for EBB registers
  powerpc/ptrace: Enable support for NT_PPPC_TAR, NT_PPC_PPR, NT_PPC_DSCR
  powerpc/ptrace: Enable NT_PPC_TM_CTAR, NT_PPC_TM_CPPR, NT_PPC_TM_CDSCR
  powerpc/ptrace: Enable support for TM SPR state
  powerpc/ptrace: Enable support for NT_PPC_CVSX
  powerpc/ptrace: Enable support for NT_PPC_CVMX
  powerpc/ptrace: Enable support for NT_PPC_CFPR
  powerpc/ptrace: Enable support for NT_PPC_CGPR
  powerpc/ptrace: Adapt gpr32_get, gpr32_set functions for transaction
  powerpc/ptrace: Enable in transaction NT_PPC_VSX ptrace requests
  powerpc/ptrace: Enable in transaction NT_PPC_VMX ptrace requests
  powerpc/ptrace: Enable in transaction NT_PRFPREG ptrace requests
  powerpc/process: Add the function flush_tmregs_to_thread
  elf: Add powerpc specific core note sections
  powerpc/mm: remove flush_tlb_page_nohash
  powerpc/mm/hugetlb: Add flush_hugetlb_tlb_range
  ...
parents 755b20f4 eea8148c
...@@ -60,6 +60,25 @@ config CODE_PATCHING_SELFTEST ...@@ -60,6 +60,25 @@ config CODE_PATCHING_SELFTEST
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
default n default n
config JUMP_LABEL_FEATURE_CHECKS
bool "Enable use of jump label for cpu/mmu_has_feature()"
depends on JUMP_LABEL
default y
help
Selecting this options enables use of jump labels for some internal
feature checks. This should generate more optimal code for those
checks.
config JUMP_LABEL_FEATURE_CHECK_DEBUG
bool "Do extra check on feature fixup calls"
depends on DEBUG_KERNEL && JUMP_LABEL_FEATURE_CHECKS
default n
help
This tries to catch incorrect usage of cpu_has_feature() and
mmu_has_feature() in the code.
If you don't know what this means, say N.
config FTR_FIXUP_SELFTEST config FTR_FIXUP_SELFTEST
bool "Run self-tests of the feature-fixup code" bool "Run self-tests of the feature-fixup code"
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
......
...@@ -11,4 +11,19 @@ extern unsigned long ...@@ -11,4 +11,19 @@ extern unsigned long
radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long len, unsigned long pgoff,
unsigned long flags); unsigned long flags);
static inline int hstate_get_psize(struct hstate *hstate)
{
unsigned long shift;
shift = huge_page_shift(hstate);
if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
return MMU_PAGE_2M;
else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
return MMU_PAGE_1G;
else {
WARN(1, "Wrong huge page shift\n");
return mmu_virtual_psize;
}
}
#endif #endif
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/book3s/64/pgtable.h> #include <asm/book3s/64/pgtable.h>
#include <asm/bug.h> #include <asm/bug.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/cpu_has_feature.h>
/* /*
* SLB * SLB
...@@ -190,6 +191,15 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) ...@@ -190,6 +191,15 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
BUG(); BUG();
} }
static inline unsigned long get_sllp_encoding(int psize)
{
unsigned long sllp;
sllp = ((mmu_psize_defs[psize].sllp & SLB_VSID_L) >> 6) |
((mmu_psize_defs[psize].sllp & SLB_VSID_LP) >> 4);
return sllp;
}
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* /*
......
...@@ -23,13 +23,6 @@ struct mmu_psize_def { ...@@ -23,13 +23,6 @@ struct mmu_psize_def {
}; };
extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
#ifdef CONFIG_PPC_RADIX_MMU
#define radix_enabled() mmu_has_feature(MMU_FTR_RADIX)
#else
#define radix_enabled() (0)
#endif
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* 64-bit classic hash table MMU */ /* 64-bit classic hash table MMU */
...@@ -107,6 +100,9 @@ extern int mmu_vmemmap_psize; ...@@ -107,6 +100,9 @@ extern int mmu_vmemmap_psize;
extern int mmu_io_psize; extern int mmu_io_psize;
/* MMU initialization */ /* MMU initialization */
void mmu_early_init_devtree(void);
void hash__early_init_devtree(void);
void radix__early_init_devtree(void);
extern void radix_init_native(void); extern void radix_init_native(void);
extern void hash__early_init_mmu(void); extern void hash__early_init_mmu(void);
extern void radix__early_init_mmu(void); extern void radix__early_init_mmu(void);
...@@ -132,11 +128,15 @@ extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base, ...@@ -132,11 +128,15 @@ extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base, static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size) phys_addr_t first_memblock_size)
{ {
if (radix_enabled()) if (early_radix_enabled())
return radix__setup_initial_memory_limit(first_memblock_base, return radix__setup_initial_memory_limit(first_memblock_base,
first_memblock_size); first_memblock_size);
return hash__setup_initial_memory_limit(first_memblock_base, return hash__setup_initial_memory_limit(first_memblock_base,
first_memblock_size); first_memblock_size);
} }
extern int (*register_process_table)(unsigned long base, unsigned long page_size,
unsigned long tbl_size);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */ #endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */
...@@ -75,11 +75,6 @@ static inline void hash__flush_tlb_page(struct vm_area_struct *vma, ...@@ -75,11 +75,6 @@ static inline void hash__flush_tlb_page(struct vm_area_struct *vma,
{ {
} }
static inline void hash__flush_tlb_page_nohash(struct vm_area_struct *vma,
unsigned long vmaddr)
{
}
static inline void hash__flush_tlb_range(struct vm_area_struct *vma, static inline void hash__flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end) unsigned long start, unsigned long end)
{ {
......
...@@ -10,26 +10,32 @@ static inline int mmu_get_ap(int psize) ...@@ -10,26 +10,32 @@ static inline int mmu_get_ap(int psize)
return mmu_psize_defs[psize].ap; return mmu_psize_defs[psize].ap;
} }
extern void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
unsigned long end, int psize);
extern void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end); unsigned long end);
extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end); extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end);
extern void radix__local_flush_tlb_mm(struct mm_struct *mm); extern void radix__local_flush_tlb_mm(struct mm_struct *mm);
extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
unsigned long ap, int nid);
extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr); extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
extern void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
int psize);
extern void radix__tlb_flush(struct mmu_gather *tlb); extern void radix__tlb_flush(struct mmu_gather *tlb);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern void radix__flush_tlb_mm(struct mm_struct *mm); extern void radix__flush_tlb_mm(struct mm_struct *mm);
extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
unsigned long ap, int nid);
extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr); extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
int psize);
#else #else
#define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm) #define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm)
#define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr) #define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr)
#define radix___flush_tlb_page(mm,addr,p,i) radix___local_flush_tlb_page(mm,addr,p,i) #define radix__flush_tlb_page_psize(mm,addr,p) radix__local_flush_tlb_page_psize(mm,addr,p)
#define radix__flush_tlb_pwc(tlb, addr) radix__local_flush_tlb_pwc(tlb, addr) #define radix__flush_tlb_pwc(tlb, addr) radix__local_flush_tlb_pwc(tlb, addr)
#endif #endif
extern void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa, extern void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
......
...@@ -7,6 +7,25 @@ ...@@ -7,6 +7,25 @@
#include <asm/book3s/64/tlbflush-hash.h> #include <asm/book3s/64/tlbflush-hash.h>
#include <asm/book3s/64/tlbflush-radix.h> #include <asm/book3s/64/tlbflush-radix.h>
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
static inline void flush_pmd_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
if (radix_enabled())
return radix__flush_pmd_tlb_range(vma, start, end);
return hash__flush_tlb_range(vma, start, end);
}
#define __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
static inline void flush_hugetlb_tlb_range(struct vm_area_struct *vma,
unsigned long start,
unsigned long end)
{
if (radix_enabled())
return radix__flush_hugetlb_tlb_range(vma, start, end);
return hash__flush_tlb_range(vma, start, end);
}
static inline void flush_tlb_range(struct vm_area_struct *vma, static inline void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end) unsigned long start, unsigned long end)
{ {
...@@ -38,14 +57,6 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma, ...@@ -38,14 +57,6 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma,
return hash__local_flush_tlb_page(vma, vmaddr); return hash__local_flush_tlb_page(vma, vmaddr);
} }
static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
unsigned long vmaddr)
{
if (radix_enabled())
return radix__flush_tlb_page(vma, vmaddr);
return hash__flush_tlb_page_nohash(vma, vmaddr);
}
static inline void tlb_flush(struct mmu_gather *tlb) static inline void tlb_flush(struct mmu_gather *tlb)
{ {
if (radix_enabled()) if (radix_enabled())
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/cpu_has_feature.h>
/* /*
* No cache flushing is required when address mappings are changed, * No cache flushing is required when address mappings are changed,
......
#ifndef __ASM_POWERPC_CPUFEATURES_H
#define __ASM_POWERPC_CPUFEATURES_H
#ifndef __ASSEMBLY__
#include <linux/bug.h>
#include <asm/cputable.h>
static inline bool early_cpu_has_feature(unsigned long feature)
{
return !!((CPU_FTRS_ALWAYS & feature) ||
(CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
}
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
#include <linux/jump_label.h>
#define NUM_CPU_FTR_KEYS 64
extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];
static __always_inline bool cpu_has_feature(unsigned long feature)
{
int i;
BUILD_BUG_ON(!__builtin_constant_p(feature));
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
if (!static_key_initialized) {
printk("Warning! cpu_has_feature() used prior to jump label init!\n");
dump_stack();
return early_cpu_has_feature(feature);
}
#endif
if (CPU_FTRS_ALWAYS & feature)
return true;
if (!(CPU_FTRS_POSSIBLE & feature))
return false;
i = __builtin_ctzl(feature);
return static_branch_likely(&cpu_feature_keys[i]);
}
#else
static inline bool cpu_has_feature(unsigned long feature)
{
return early_cpu_has_feature(feature);
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ASM_POWERPC_CPUFEATURE_H */
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __ASM_POWERPC_CPUTABLE_H #define __ASM_POWERPC_CPUTABLE_H
#include <linux/types.h>
#include <asm/asm-compat.h> #include <asm/asm-compat.h>
#include <asm/feature-fixups.h> #include <asm/feature-fixups.h>
#include <uapi/asm/cputable.h> #include <uapi/asm/cputable.h>
...@@ -122,6 +123,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, ...@@ -122,6 +123,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
extern const char *powerpc_base_platform; extern const char *powerpc_base_platform;
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
extern void cpu_feature_keys_init(void);
#else
static inline void cpu_feature_keys_init(void) { }
#endif
/* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */ /* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */
enum { enum {
TLB_INVAL_SCOPE_GLOBAL = 0, /* invalidate all TLBs */ TLB_INVAL_SCOPE_GLOBAL = 0, /* invalidate all TLBs */
...@@ -576,14 +583,6 @@ enum { ...@@ -576,14 +583,6 @@ enum {
}; };
#endif /* __powerpc64__ */ #endif /* __powerpc64__ */
static inline int cpu_has_feature(unsigned long feature)
{
return (CPU_FTRS_ALWAYS & feature) ||
(CPU_FTRS_POSSIBLE
& cur_cpu_spec->cpu_features
& feature);
}
#define HBP_NUM 1 #define HBP_NUM 1
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
......
...@@ -28,6 +28,7 @@ static inline void setup_cputime_one_jiffy(void) { } ...@@ -28,6 +28,7 @@ static inline void setup_cputime_one_jiffy(void) { }
#include <asm/div64.h> #include <asm/div64.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/param.h> #include <asm/param.h>
#include <asm/cpu_has_feature.h>
typedef u64 __nocast cputime_t; typedef u64 __nocast cputime_t;
typedef u64 __nocast cputime64_t; typedef u64 __nocast cputime64_t;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/ppc-opcode.h> #include <asm/ppc-opcode.h>
#include <asm/cpu_has_feature.h>
#define PPC_DBELL_MSG_BRDCAST (0x04000000) #define PPC_DBELL_MSG_BRDCAST (0x04000000)
#define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36)) #define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/cpu_has_feature.h>
typedef struct { typedef struct {
unsigned int base; unsigned int base;
......
...@@ -147,7 +147,7 @@ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, ...@@ -147,7 +147,7 @@ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
{ {
pte_t pte; pte_t pte;
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
flush_tlb_page(vma, addr); flush_hugetlb_page(vma, addr);
} }
static inline int huge_pte_none(pte_t pte) static inline int huge_pte_none(pte_t pte)
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
static __always_inline bool arch_static_branch(struct static_key *key, bool branch) static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{ {
asm_volatile_goto("1:\n\t" asm_volatile_goto("1:\n\t"
"nop\n\t" "nop # arch_static_branch\n\t"
".pushsection __jump_table, \"aw\"\n\t" ".pushsection __jump_table, \"aw\"\n\t"
JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t" JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
".popsection \n\t" ".popsection \n\t"
...@@ -36,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran ...@@ -36,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
{ {
asm_volatile_goto("1:\n\t" asm_volatile_goto("1:\n\t"
"b %l[l_yes]\n\t" "b %l[l_yes] # arch_static_branch_jump\n\t"
".pushsection __jump_table, \"aw\"\n\t" ".pushsection __jump_table, \"aw\"\n\t"
JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t" JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
".popsection \n\t" ".popsection \n\t"
......
...@@ -181,8 +181,7 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, ...@@ -181,8 +181,7 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
switch (b_psize) { switch (b_psize) {
case MMU_PAGE_4K: case MMU_PAGE_4K:
sllp = ((mmu_psize_defs[a_psize].sllp & SLB_VSID_L) >> 6) | sllp = get_sllp_encoding(a_psize);
((mmu_psize_defs[a_psize].sllp & SLB_VSID_LP) >> 4);
rb |= sllp << 5; /* AP field */ rb |= sllp << 5; /* AP field */
rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */ rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */
break; break;
......
...@@ -219,8 +219,6 @@ struct machdep_calls { ...@@ -219,8 +219,6 @@ struct machdep_calls {
#ifdef CONFIG_ARCH_RANDOM #ifdef CONFIG_ARCH_RANDOM
int (*get_random_seed)(unsigned long *v); int (*get_random_seed)(unsigned long *v);
#endif #endif
int (*register_process_table)(unsigned long base, unsigned long page_size,
unsigned long tbl_size);
}; };
extern void e500_idle(void); extern void e500_idle(void);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/cpu_has_feature.h>
/* /*
* This file is included by linux/mman.h, so we can't use cacl_vm_prot_bits() * This file is included by linux/mman.h, so we can't use cacl_vm_prot_bits()
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
*/ */
/* /*
* First half is MMU families * MMU families
*/ */
#define MMU_FTR_HPTE_TABLE ASM_CONST(0x00000001) #define MMU_FTR_HPTE_TABLE ASM_CONST(0x00000001)
#define MMU_FTR_TYPE_8xx ASM_CONST(0x00000002) #define MMU_FTR_TYPE_8xx ASM_CONST(0x00000002)
...@@ -21,9 +21,13 @@ ...@@ -21,9 +21,13 @@
#define MMU_FTR_TYPE_FSL_E ASM_CONST(0x00000010) #define MMU_FTR_TYPE_FSL_E ASM_CONST(0x00000010)
#define MMU_FTR_TYPE_47x ASM_CONST(0x00000020) #define MMU_FTR_TYPE_47x ASM_CONST(0x00000020)
/* Radix page table supported and enabled */
#define MMU_FTR_TYPE_RADIX ASM_CONST(0x00000040)
/* /*
* This is individual features * Individual features below.
*/ */
/* /*
* We need to clear top 16bits of va (from the remaining 64 bits )in * We need to clear top 16bits of va (from the remaining 64 bits )in
* tlbie* instructions * tlbie* instructions
...@@ -93,11 +97,6 @@ ...@@ -93,11 +97,6 @@
*/ */
#define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000) #define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000)
/*
* Radix page table available
*/
#define MMU_FTR_RADIX ASM_CONST(0x80000000)
/* MMU feature bit sets for various CPUs */ /* MMU feature bit sets for various CPUs */
#define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \ #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \
MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2 MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
...@@ -113,6 +112,7 @@ ...@@ -113,6 +112,7 @@
#define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ #define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
MMU_FTR_CI_LARGE_PAGE | MMU_FTR_NO_SLBIE_B MMU_FTR_CI_LARGE_PAGE | MMU_FTR_NO_SLBIE_B
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/bug.h>
#include <asm/cputable.h> #include <asm/cputable.h>
#ifdef CONFIG_PPC_FSL_BOOK3E #ifdef CONFIG_PPC_FSL_BOOK3E
...@@ -131,20 +131,71 @@ enum { ...@@ -131,20 +131,71 @@ enum {
MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_CI_LARGE_PAGE | MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_CI_LARGE_PAGE |
MMU_FTR_1T_SEGMENT | MMU_FTR_TLBIE_CROP_VA | MMU_FTR_1T_SEGMENT | MMU_FTR_TLBIE_CROP_VA |
#ifdef CONFIG_PPC_RADIX_MMU #ifdef CONFIG_PPC_RADIX_MMU
MMU_FTR_RADIX | MMU_FTR_TYPE_RADIX |
#endif #endif
0, 0,
}; };
static inline int mmu_has_feature(unsigned long feature) static inline bool early_mmu_has_feature(unsigned long feature)
{ {
return (MMU_FTRS_POSSIBLE & cur_cpu_spec->mmu_features & feature); return !!(MMU_FTRS_POSSIBLE & cur_cpu_spec->mmu_features & feature);
}
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
#include <linux/jump_label.h>
#define NUM_MMU_FTR_KEYS 32
extern struct static_key_true mmu_feature_keys[NUM_MMU_FTR_KEYS];
extern void mmu_feature_keys_init(void);
static __always_inline bool mmu_has_feature(unsigned long feature)
{
int i;
BUILD_BUG_ON(!__builtin_constant_p(feature));
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
if (!static_key_initialized) {
printk("Warning! mmu_has_feature() used prior to jump label init!\n");
dump_stack();
return early_mmu_has_feature(feature);
}
#endif
if (!(MMU_FTRS_POSSIBLE & feature))
return false;
i = __builtin_ctzl(feature);
return static_branch_likely(&mmu_feature_keys[i]);
} }
static inline void mmu_clear_feature(unsigned long feature) static inline void mmu_clear_feature(unsigned long feature)
{ {
int i;
i = __builtin_ctzl(feature);
cur_cpu_spec->mmu_features &= ~feature; cur_cpu_spec->mmu_features &= ~feature;
static_branch_disable(&mmu_feature_keys[i]);
} }
#else
static inline void mmu_feature_keys_init(void)
{
}
static inline bool mmu_has_feature(unsigned long feature)
{
return early_mmu_has_feature(feature);
}
static inline void mmu_clear_feature(unsigned long feature)
{
cur_cpu_spec->mmu_features &= ~feature;
}
#endif /* CONFIG_JUMP_LABEL */
extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup; extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
...@@ -164,6 +215,28 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr) ...@@ -164,6 +215,28 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
} }
#endif /* !CONFIG_DEBUG_VM */ #endif /* !CONFIG_DEBUG_VM */
#ifdef CONFIG_PPC_RADIX_MMU
static inline bool radix_enabled(void)
{
return mmu_has_feature(MMU_FTR_TYPE_RADIX);
}
static inline bool early_radix_enabled(void)
{
return early_mmu_has_feature(MMU_FTR_TYPE_RADIX);
}
#else
static inline bool radix_enabled(void)
{
return false;
}
static inline bool early_radix_enabled(void)
{
return false;
}
#endif
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
/* The kernel use the constants below to index in the page sizes array. /* The kernel use the constants below to index in the page sizes array.
...@@ -210,6 +283,7 @@ extern void early_init_mmu(void); ...@@ -210,6 +283,7 @@ extern void early_init_mmu(void);
extern void early_init_mmu_secondary(void); extern void early_init_mmu_secondary(void);
extern void setup_initial_memory_limit(phys_addr_t first_memblock_base, extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size); phys_addr_t first_memblock_size);
static inline void mmu_early_init_devtree(void) { }
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif #endif
...@@ -230,9 +304,5 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base, ...@@ -230,9 +304,5 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
# include <asm/mmu-8xx.h> # include <asm/mmu-8xx.h>
#endif #endif
#ifndef radix_enabled
#define radix_enabled() (0)
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MMU_H_ */ #endif /* _ASM_POWERPC_MMU_H_ */
...@@ -1256,15 +1256,6 @@ static inline void msr_check_and_clear(unsigned long bits) ...@@ -1256,15 +1256,6 @@ static inline void msr_check_and_clear(unsigned long bits)
__msr_check_and_clear(bits); __msr_check_and_clear(bits);
} }
static inline unsigned long mfvtb (void)
{
#ifdef CONFIG_PPC_BOOK3S_64
if (cpu_has_feature(CPU_FTR_ARCH_207S))
return mfspr(SPRN_VTB);
#endif
return 0;
}
#ifdef __powerpc64__ #ifdef __powerpc64__
#if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E) #if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E)
#define mftb() ({unsigned long rval; \ #define mftb() ({unsigned long rval; \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment