diff options
Diffstat (limited to 'arch/powerpc/include')
27 files changed, 301 insertions, 96 deletions
| diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h index 486ab7889121..47228b177478 100644 --- a/arch/powerpc/include/asm/atomic.h +++ b/arch/powerpc/include/asm/atomic.h @@ -27,14 +27,22 @@ static __inline__ int arch_atomic_read(const atomic_t *v)  {  	int t; -	__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); +	/* -mprefixed can generate offsets beyond range, fall back hack */ +	if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) +		__asm__ __volatile__("lwz %0,0(%1)" : "=r"(t) : "b"(&v->counter)); +	else +		__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter));  	return t;  }  static __inline__ void arch_atomic_set(atomic_t *v, int i)  { -	__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); +	/* -mprefixed can generate offsets beyond range, fall back hack */ +	if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) +		__asm__ __volatile__("stw %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter)); +	else +		__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i));  }  #define ATOMIC_OP(op, asm_op, suffix, sign, ...)			\ @@ -130,35 +138,6 @@ ATOMIC_OPS(xor, xor, "", K)  #define arch_atomic_xchg_relaxed(v, new) \  	arch_xchg_relaxed(&((v)->counter), (new)) -/* - * Don't want to override the generic atomic_try_cmpxchg_acquire, because - * we add a lock hint to the lwarx, which may not be wanted for the - * _acquire case (and is not used by the other _acquire variants so it - * would be a surprise). - */ -static __always_inline bool -arch_atomic_try_cmpxchg_lock(atomic_t *v, int *old, int new) -{ -	int r, o = *old; -	unsigned int eh = IS_ENABLED(CONFIG_PPC64); - -	__asm__ __volatile__ ( -"1:	lwarx	%0,0,%2,%[eh]	# atomic_try_cmpxchg_acquire		\n" -"	cmpw	0,%0,%3							\n" -"	bne-	2f							\n" -"	stwcx.	%4,0,%2							\n" -"	bne-	1b							\n" -"\t"	PPC_ACQUIRE_BARRIER "						\n" -"2:									\n" -	: "=&r" (r), "+m" (v->counter) -	: "r" (&v->counter), "r" (o), "r" (new), [eh] "n" (eh) -	: "cr0", "memory"); - -	if (unlikely(r != o)) -		*old = r; -	return likely(r == o); -} -  /**   * atomic_fetch_add_unless - add unless the number is a given value   * @v: pointer of type atomic_t @@ -226,14 +205,22 @@ static __inline__ s64 arch_atomic64_read(const atomic64_t *v)  {  	s64 t; -	__asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); +	/* -mprefixed can generate offsets beyond range, fall back hack */ +	if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) +		__asm__ __volatile__("ld %0,0(%1)" : "=r"(t) : "b"(&v->counter)); +	else +		__asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter));  	return t;  }  static __inline__ void arch_atomic64_set(atomic64_t *v, s64 i)  { -	__asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); +	/* -mprefixed can generate offsets beyond range, fall back hack */ +	if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) +		__asm__ __volatile__("std %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter)); +	else +		__asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i));  }  #define ATOMIC64_OP(op, asm_op)						\ diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h index 2bbc0fcce04a..0d0c1447ecf0 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h @@ -121,7 +121,8 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,  #define flush_tlb_fix_spurious_fault flush_tlb_fix_spurious_fault  static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma, -						unsigned long address) +						unsigned long address, +						pte_t *ptep)  {  	/*  	 * Book3S 64 does not require spurious fault flushes because the PTE @@ -148,6 +149,11 @@ static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma,  	 */  } +static inline bool __pte_protnone(unsigned long pte) +{ +	return (pte & (pgprot_val(PAGE_NONE) | _PAGE_RWX)) == pgprot_val(PAGE_NONE); +} +  static inline bool __pte_flags_need_flush(unsigned long oldval,  					  unsigned long newval)  { @@ -164,8 +170,8 @@ static inline bool __pte_flags_need_flush(unsigned long oldval,  	/*  	 * We do not expect kernel mappings or non-PTEs or not-present PTEs.  	 */ -	VM_WARN_ON_ONCE(oldval & _PAGE_PRIVILEGED); -	VM_WARN_ON_ONCE(newval & _PAGE_PRIVILEGED); +	VM_WARN_ON_ONCE(!__pte_protnone(oldval) && oldval & _PAGE_PRIVILEGED); +	VM_WARN_ON_ONCE(!__pte_protnone(newval) && newval & _PAGE_PRIVILEGED);  	VM_WARN_ON_ONCE(!(oldval & _PAGE_PTE));  	VM_WARN_ON_ONCE(!(newval & _PAGE_PTE));  	VM_WARN_ON_ONCE(!(oldval & _PAGE_PRESENT)); diff --git a/arch/powerpc/include/asm/cmpxchg.h b/arch/powerpc/include/asm/cmpxchg.h index d0ea0571e79a..dbb50c06f0bf 100644 --- a/arch/powerpc/include/asm/cmpxchg.h +++ b/arch/powerpc/include/asm/cmpxchg.h @@ -229,7 +229,7 @@ __xchg_local(void *ptr, unsigned long x, unsigned int size)  		return __xchg_u64_local(ptr, x);  #endif  	} -	BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg"); +	BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_local");  	return x;  } @@ -248,7 +248,7 @@ __xchg_relaxed(void *ptr, unsigned long x, unsigned int size)  		return __xchg_u64_relaxed(ptr, x);  #endif  	} -	BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_local"); +	BUILD_BUG_ON_MSG(1, "Unsupported size for __xchg_relaxed");  	return x;  }  #define arch_xchg_local(ptr,x)						     \ diff --git a/arch/powerpc/include/asm/cpufeature.h b/arch/powerpc/include/asm/cpufeature.h index f6f790a90367..2dcc66225e7f 100644 --- a/arch/powerpc/include/asm/cpufeature.h +++ b/arch/powerpc/include/asm/cpufeature.h @@ -22,6 +22,7 @@   */  #define PPC_MODULE_FEATURE_VEC_CRYPTO			(32 + ilog2(PPC_FEATURE2_VEC_CRYPTO)) +#define PPC_MODULE_FEATURE_P10				(32 + ilog2(PPC_FEATURE2_ARCH_3_1))  #define cpu_feature(x)		(x) diff --git a/arch/powerpc/include/asm/fb.h b/arch/powerpc/include/asm/fb.h index 6541ab77c5b9..5f1a2e5f7654 100644 --- a/arch/powerpc/include/asm/fb.h +++ b/arch/powerpc/include/asm/fb.h @@ -2,8 +2,8 @@  #ifndef _ASM_FB_H_  #define _ASM_FB_H_ -#include <linux/fb.h>  #include <linux/fs.h> +  #include <asm/page.h>  static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, @@ -13,10 +13,8 @@ static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,  						 vma->vm_end - vma->vm_start,  						 vma->vm_page_prot);  } +#define fb_pgprotect fb_pgprotect -static inline int fb_is_primary_device(struct fb_info *info) -{ -	return 0; -} +#include <asm-generic/fb.h>  #endif /* _ASM_FB_H_ */ diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index ed6db13a1d7c..69ae9cf57d50 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h @@ -56,6 +56,7 @@  #define FW_FEATURE_FORM2_AFFINITY ASM_CONST(0x0000020000000000)  #define FW_FEATURE_ENERGY_SCALE_INFO ASM_CONST(0x0000040000000000)  #define FW_FEATURE_WATCHDOG	ASM_CONST(0x0000080000000000) +#define FW_FEATURE_PLPKS	ASM_CONST(0x0000100000000000)  #ifndef __ASSEMBLY__ @@ -77,7 +78,8 @@ enum {  		FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE |  		FW_FEATURE_PAPR_SCM | FW_FEATURE_ULTRAVISOR |  		FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY | -		FW_FEATURE_ENERGY_SCALE_INFO | FW_FEATURE_WATCHDOG, +		FW_FEATURE_ENERGY_SCALE_INFO | FW_FEATURE_WATCHDOG | +		FW_FEATURE_PLPKS,  	FW_FEATURE_PSERIES_ALWAYS = 0,  	FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_ULTRAVISOR,  	FW_FEATURE_POWERNV_ALWAYS = 0, diff --git a/arch/powerpc/include/asm/idle.h b/arch/powerpc/include/asm/idle.h index accd1f50085a..00f360667391 100644 --- a/arch/powerpc/include/asm/idle.h +++ b/arch/powerpc/include/asm/idle.h @@ -9,17 +9,17 @@ DECLARE_PER_CPU(u64, idle_spurr_cycles);  DECLARE_PER_CPU(u64, idle_entry_purr_snap);  DECLARE_PER_CPU(u64, idle_entry_spurr_snap); -static inline void snapshot_purr_idle_entry(void) +static __always_inline void snapshot_purr_idle_entry(void)  {  	*this_cpu_ptr(&idle_entry_purr_snap) = mfspr(SPRN_PURR);  } -static inline void snapshot_spurr_idle_entry(void) +static __always_inline void snapshot_spurr_idle_entry(void)  {  	*this_cpu_ptr(&idle_entry_spurr_snap) = mfspr(SPRN_SPURR);  } -static inline void update_idle_purr_accounting(void) +static __always_inline void update_idle_purr_accounting(void)  {  	u64 wait_cycles;  	u64 in_purr = *this_cpu_ptr(&idle_entry_purr_snap); @@ -29,7 +29,7 @@ static inline void update_idle_purr_accounting(void)  	get_lppaca()->wait_state_cycles = cpu_to_be64(wait_cycles);  } -static inline void update_idle_spurr_accounting(void) +static __always_inline void update_idle_spurr_accounting(void)  {  	u64 *idle_spurr_cycles_ptr = this_cpu_ptr(&idle_spurr_cycles);  	u64 in_spurr = *this_cpu_ptr(&idle_entry_spurr_snap); @@ -37,7 +37,7 @@ static inline void update_idle_spurr_accounting(void)  	*idle_spurr_cycles_ptr += mfspr(SPRN_SPURR) - in_spurr;  } -static inline void pseries_idle_prolog(void) +static __always_inline void pseries_idle_prolog(void)  {  	ppc64_runlatch_off();  	snapshot_purr_idle_entry(); @@ -49,7 +49,7 @@ static inline void pseries_idle_prolog(void)  	get_lppaca()->idle = 1;  } -static inline void pseries_idle_epilog(void) +static __always_inline void pseries_idle_epilog(void)  {  	update_idle_purr_accounting();  	update_idle_spurr_accounting(); diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index fc112a91d0c2..f1e657c9bbe8 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h @@ -97,6 +97,42 @@ extern bool isa_io_special;   *   */ +/* -mprefixed can generate offsets beyond range, fall back hack */ +#ifdef CONFIG_PPC_KERNEL_PREFIXED +#define DEF_MMIO_IN_X(name, size, insn)				\ +static inline u##size name(const volatile u##size __iomem *addr)	\ +{									\ +	u##size ret;							\ +	__asm__ __volatile__("sync;"#insn" %0,0,%1;twi 0,%0,0;isync"	\ +		: "=r" (ret) : "r" (addr) : "memory");			\ +	return ret;							\ +} + +#define DEF_MMIO_OUT_X(name, size, insn)				\ +static inline void name(volatile u##size __iomem *addr, u##size val)	\ +{									\ +	__asm__ __volatile__("sync;"#insn" %1,0,%0"			\ +		: : "r" (addr), "r" (val) : "memory");			\ +	mmiowb_set_pending();						\ +} + +#define DEF_MMIO_IN_D(name, size, insn)				\ +static inline u##size name(const volatile u##size __iomem *addr)	\ +{									\ +	u##size ret;							\ +	__asm__ __volatile__("sync;"#insn" %0,0(%1);twi 0,%0,0;isync"\ +		: "=r" (ret) : "b" (addr) : "memory");	\ +	return ret;							\ +} + +#define DEF_MMIO_OUT_D(name, size, insn)				\ +static inline void name(volatile u##size __iomem *addr, u##size val)	\ +{									\ +	__asm__ __volatile__("sync;"#insn" %1,0(%0)"			\ +		: : "b" (addr), "r" (val) : "memory");	\ +	mmiowb_set_pending();						\ +} +#else  #define DEF_MMIO_IN_X(name, size, insn)				\  static inline u##size name(const volatile u##size __iomem *addr)	\  {									\ @@ -130,6 +166,7 @@ static inline void name(volatile u##size __iomem *addr, u##size val)	\  		: "=m<>" (*addr) : "r" (val) : "memory");	\  	mmiowb_set_pending();						\  } +#endif  DEF_MMIO_IN_D(in_8,     8, lbz);  DEF_MMIO_OUT_D(out_8,   8, stb); diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 7e29c73e3dd4..678b5bdc79b1 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -175,7 +175,7 @@ struct iommu_table_group_ops {  	long (*unset_window)(struct iommu_table_group *table_group,  			int num);  	/* Switch ownership from platform code to external user (e.g. VFIO) */ -	void (*take_ownership)(struct iommu_table_group *table_group); +	long (*take_ownership)(struct iommu_table_group *table_group);  	/* Switch ownership from external user (e.g. VFIO) back to core */  	void (*release_ownership)(struct iommu_table_group *table_group);  }; @@ -215,6 +215,8 @@ extern long iommu_tce_xchg_no_kill(struct mm_struct *mm,  		enum dma_data_direction *direction);  extern void iommu_tce_kill(struct iommu_table *tbl,  		unsigned long entry, unsigned long pages); + +extern struct iommu_table_group_ops spapr_tce_table_group_ops;  #else  static inline void iommu_register_group(struct iommu_table_group *table_group,  					int pci_domain_number, @@ -303,8 +305,6 @@ extern int iommu_tce_check_gpa(unsigned long page_shift,  		iommu_tce_check_gpa((tbl)->it_page_shift, (gpa)))  extern void iommu_flush_tce(struct iommu_table *tbl); -extern int iommu_take_ownership(struct iommu_table *tbl); -extern void iommu_release_ownership(struct iommu_table *tbl);  extern enum dma_data_direction iommu_tce_direction(unsigned long tce);  extern unsigned long iommu_direction_to_tce_perm(enum dma_data_direction dir); diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 959f566a455c..14ee0dece853 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -758,7 +758,7 @@ struct kvm_vcpu_arch {  	u8 prodded;  	u8 doorbell_request;  	u8 irq_pending; /* Used by XIVE to signal pending guest irqs */ -	u32 last_inst; +	unsigned long last_inst;  	struct rcuwait wait;  	struct rcuwait *waitp; @@ -818,7 +818,7 @@ struct kvm_vcpu_arch {  	u64 busy_stolen;  	u64 busy_preempt; -	u32 emul_inst; +	u64 emul_inst;  	u32 online; diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 6bef23d6d0e3..79a9c0bb8bba 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -28,6 +28,7 @@  #include <asm/xive.h>  #include <asm/cpu_has_feature.h>  #endif +#include <asm/inst.h>  /*   * KVMPPC_INST_SW_BREAKPOINT is debug Instruction @@ -84,7 +85,8 @@ extern int kvmppc_handle_vsx_store(struct kvm_vcpu *vcpu,  				int is_default_endian);  extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, -				 enum instruction_fetch_type type, u32 *inst); +				 enum instruction_fetch_type type, +				 unsigned long *inst);  extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,  		     bool data); @@ -126,25 +128,34 @@ extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);  extern int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu);  extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu); -extern void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu, ulong flags); + +extern void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu, +					    ulong srr1_flags);  extern void kvmppc_core_queue_syscall(struct kvm_vcpu *vcpu); -extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags); -extern void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu); -extern void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu); -extern void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu); +extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, +				      ulong srr1_flags); +extern void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu, +					ulong srr1_flags); +extern void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu, +					  ulong srr1_flags); +extern void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu, +					  ulong srr1_flags);  extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);  extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);  extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,                                         struct kvm_interrupt *irq);  extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu); -extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, ulong dear_flags, +extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, +					ulong dear_flags,  					ulong esr_flags);  extern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, -					   ulong dear_flags, -					   ulong esr_flags); +					   ulong srr1_flags, +					   ulong dar, +					   ulong dsisr);  extern void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu);  extern void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, -					   ulong esr_flags); +					   ulong srr1_flags); +  extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);  extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu); @@ -156,7 +167,7 @@ extern void kvmppc_map_magic(struct kvm_vcpu *vcpu);  extern int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order);  extern void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info); -extern long kvmppc_alloc_reset_hpt(struct kvm *kvm, int order); +extern int kvmppc_alloc_reset_hpt(struct kvm *kvm, int order);  extern void kvmppc_free_hpt(struct kvm_hpt_info *info);  extern void kvmppc_rmap_reset(struct kvm *kvm);  extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu, @@ -170,7 +181,7 @@ extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm);  extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm);  extern void kvmppc_setup_partition_table(struct kvm *kvm); -extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, +extern int kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,  				struct kvm_create_spapr_tce_64 *args);  #define kvmppc_ioba_validate(stt, ioba, npages)                         \  		(iommu_tce_check_ioba((stt)->page_shift, (stt)->offset, \ @@ -211,10 +222,10 @@ extern void kvmppc_bookehv_exit(void);  extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);  extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *); -extern long kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm, -					    struct kvm_ppc_resize_hpt *rhpt); -extern long kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm, +extern int kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,  					   struct kvm_ppc_resize_hpt *rhpt); +extern int kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm, +					  struct kvm_ppc_resize_hpt *rhpt);  int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq); @@ -286,8 +297,8 @@ struct kvmppc_ops {  	int (*emulate_mtspr)(struct kvm_vcpu *vcpu, int sprn, ulong spr_val);  	int (*emulate_mfspr)(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val);  	void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu); -	long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl, -			      unsigned long arg); +	int (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl, +			     unsigned long arg);  	int (*hcall_implemented)(unsigned long hcall);  	int (*irq_bypass_add_producer)(struct irq_bypass_consumer *,  				       struct irq_bypass_producer *); @@ -315,7 +326,7 @@ extern struct kvmppc_ops *kvmppc_hv_ops;  extern struct kvmppc_ops *kvmppc_pr_ops;  static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu, -				enum instruction_fetch_type type, u32 *inst) +				enum instruction_fetch_type type, ppc_inst_t *inst)  {  	int ret = EMULATE_DONE;  	u32 fetched_inst; @@ -326,15 +337,30 @@ static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,  		ret = kvmppc_load_last_inst(vcpu, type, &vcpu->arch.last_inst);  	/*  Write fetch_failed unswapped if the fetch failed */ -	if (ret == EMULATE_DONE) -		fetched_inst = kvmppc_need_byteswap(vcpu) ? -				swab32(vcpu->arch.last_inst) : -				vcpu->arch.last_inst; -	else -		fetched_inst = vcpu->arch.last_inst; +	if (ret != EMULATE_DONE) { +		*inst = ppc_inst(KVM_INST_FETCH_FAILED); +		return ret; +	} + +#ifdef CONFIG_PPC64 +	/* Is this a prefixed instruction? */ +	if ((vcpu->arch.last_inst >> 32) != 0) { +		u32 prefix = vcpu->arch.last_inst >> 32; +		u32 suffix = vcpu->arch.last_inst; +		if (kvmppc_need_byteswap(vcpu)) { +			prefix = swab32(prefix); +			suffix = swab32(suffix); +		} +		*inst = ppc_inst_prefix(prefix, suffix); +		return EMULATE_DONE; +	} +#endif -	*inst = fetched_inst; -	return ret; +	fetched_inst = kvmppc_need_byteswap(vcpu) ? +		swab32(vcpu->arch.last_inst) : +		vcpu->arch.last_inst; +	*inst = ppc_inst(fetched_inst); +	return EMULATE_DONE;  }  static inline bool is_kvmppc_hv_enabled(struct kvm *kvm) diff --git a/arch/powerpc/include/asm/local.h b/arch/powerpc/include/asm/local.h index bc4bd19b7fc2..45492fb5bf22 100644 --- a/arch/powerpc/include/asm/local.h +++ b/arch/powerpc/include/asm/local.h @@ -90,6 +90,17 @@ static __inline__ long local_cmpxchg(local_t *l, long o, long n)  	return t;  } +static __inline__ bool local_try_cmpxchg(local_t *l, long *po, long n) +{ +	long o = *po, r; + +	r = local_cmpxchg(l, o, n); +	if (unlikely(r != o)) +		*po = r; + +	return likely(r == o); +} +  static __inline__ long local_xchg(local_t *l, long n)  {  	long t; diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 459736d5e511..4f6e7d7ee388 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -20,7 +20,8 @@ struct kimage;  struct pci_host_bridge;  struct machdep_calls { -	char		*name; +	const char	*name; +	const char	*compatible;  #ifdef CONFIG_PPC64  #ifdef CONFIG_PM  	void		(*iommu_restore)(void); diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 09e2ffd360bb..ac53606c2594 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h @@ -27,8 +27,13 @@ struct ppc_plt_entry {  struct mod_arch_specific {  #ifdef __powerpc64__  	unsigned int stubs_section;	/* Index of stubs section in module */ +#ifdef CONFIG_PPC_KERNEL_PCREL +	unsigned int got_section;	/* What section is the GOT? */ +	unsigned int pcpu_section;	/* .data..percpu section */ +#else  	unsigned int toc_section;	/* What section is the TOC? */  	bool toc_fixed;			/* Have we fixed up .TOC.? */ +#endif  	/* For module function descriptor dereference */  	unsigned long start_opd; @@ -52,12 +57,15 @@ struct mod_arch_specific {  /*   * Select ELF headers. - * Make empty section for module_frob_arch_sections to expand. + * Make empty sections for module_frob_arch_sections to expand.   */  #ifdef __powerpc64__  #    ifdef MODULE  	asm(".section .stubs,\"ax\",@nobits; .align 3; .previous"); +#        ifdef CONFIG_PPC_KERNEL_PCREL +	    asm(".section .mygot,\"a\",@nobits; .align 3; .previous"); +#        endif  #    endif  #else  #    ifdef MODULE diff --git a/arch/powerpc/include/asm/mpc8260.h b/arch/powerpc/include/asm/mpc8260.h index fd8c5707425b..155114bbd1a2 100644 --- a/arch/powerpc/include/asm/mpc8260.h +++ b/arch/powerpc/include/asm/mpc8260.h @@ -13,10 +13,6 @@  #ifdef CONFIG_8260 -#if defined(CONFIG_PQ2ADS) || defined (CONFIG_PQ2FADS) -#include <platforms/82xx/pq2ads.h> -#endif -  #ifdef CONFIG_PCI_8260  #include <platforms/82xx/m82xx_pci.h>  #endif diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 0ab3511a47d7..da0377f46597 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -88,7 +88,9 @@ struct paca_struct {  	u16 lock_token;			/* Constant 0x8000, used in locks */  #endif +#ifndef CONFIG_PPC_KERNEL_PCREL  	u64 kernel_toc;			/* Kernel TOC address */ +#endif  	u64 kernelbase;			/* Base address of kernel */  	u64 kernel_msr;			/* MSR while running in kernel */  	void *emergency_sp;		/* pointer to emergency stack */ diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 71c1d26f2400..2aa3a091ef20 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -8,6 +8,7 @@  #include <linux/list.h>  #include <linux/ioport.h>  #include <linux/numa.h> +#include <linux/iommu.h>  struct device_node; @@ -44,6 +45,9 @@ struct pci_controller_ops {  #endif  	void		(*shutdown)(struct pci_controller *hose); + +	struct iommu_group *(*device_group)(struct pci_controller *hose, +					    struct pci_dev *pdev);  };  /* @@ -131,6 +135,9 @@ struct pci_controller {  	struct irq_domain	*dev_domain;  	struct irq_domain	*msi_domain;  	struct fwnode_handle	*fwnode; + +	/* iommu_ops support */ +	struct iommu_device	iommu;  };  /* These are used for config access before all the PCI probing diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 21e33e46f4b8..ca5a0da7df4e 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -120,11 +120,18 @@   * 16-bit immediate helper macros: HA() is for use with sign-extending instrs   * (e.g. LD, ADDI).  If the bottom 16 bits is "-ve", add another bit into the   * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000). + * + * XXX: should these mask out possible sign bits?   */  #define IMM_H(i)                ((uintptr_t)(i)>>16)  #define IMM_HA(i)               (((uintptr_t)(i)>>16) +                       \  					(((uintptr_t)(i) & 0x8000) >> 15)) +/* + * 18-bit immediate helper for prefix 18-bit upper immediate si0 field. + */ +#define IMM_H18(i)              (((uintptr_t)(i)>>16) & 0x3ffff) +  /* opcode and xopcode for instructions */  #define OP_PREFIX	1 @@ -306,6 +313,7 @@  #define PPC_PREFIX_8LS			0x04000000  /* Prefixed instructions */ +#define PPC_INST_PADDI			0x38000000  #define PPC_INST_PLD			0xe4000000  #define PPC_INST_PSTD			0xf4000000 diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index f6cf0159024e..d9fcff575027 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -57,11 +57,19 @@ void eeh_sysfs_remove_device(struct pci_dev *pdev);  #endif /* CONFIG_EEH */ +#ifdef CONFIG_FSL_ULI1575 +void __init uli_init(void); +#endif /* CONFIG_FSL_ULI1575 */ +  #define PCI_BUSNO(bdfn) ((bdfn >> 8) & 0xff)  #else /* CONFIG_PCI */  static inline void init_pci_config_tokens(void) { }  #endif /* !CONFIG_PCI */ +#if !defined(CONFIG_PCI) || !defined(CONFIG_FSL_ULI1575) +static inline void __init uli_init(void) {} +#endif /* !defined(CONFIG_PCI) || !defined(CONFIG_FSL_ULI1575) */ +  #endif /* __KERNEL__ */  #endif /* _ASM_POWERPC_PPC_PCI_H */ diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index d2f44612f4b0..5f05a984b103 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h @@ -181,6 +181,15 @@  #ifdef __KERNEL__  /* + * Used to name C functions called from asm + */ +#ifdef CONFIG_PPC_KERNEL_PCREL +#define CFUNC(name) name@notoc +#else +#define CFUNC(name) name +#endif + +/*   * We use __powerpc64__ here because we want the compat VDSO to use the 32-bit   * version below in the else case of the ifdef.   */ @@ -207,6 +216,9 @@  	.globl name; \  name: +#ifdef CONFIG_PPC_KERNEL_PCREL +#define _GLOBAL_TOC _GLOBAL +#else  #define _GLOBAL_TOC(name) \  	.align 2 ; \  	.type name,@function; \ @@ -215,6 +227,7 @@ name: \  0:	addis r2,r12,(.TOC.-0b)@ha; \  	addi r2,r2,(.TOC.-0b)@l; \  	.localentry name,.-name +#endif  #define DOTSYM(a)	a @@ -346,8 +359,13 @@ n:  #ifdef __powerpc64__ +#ifdef CONFIG_PPC_KERNEL_PCREL +#define __LOAD_PACA_TOC(reg)			\ +	li	reg,-1 +#else  #define __LOAD_PACA_TOC(reg)			\  	ld	reg,PACATOC(r13) +#endif  #define LOAD_PACA_TOC()				\  	__LOAD_PACA_TOC(r2) @@ -361,9 +379,15 @@ n:  	ori	reg, reg, (expr)@l;		\  	rldimi	reg, tmp, 32, 0 +#ifdef CONFIG_PPC_KERNEL_PCREL +#define LOAD_REG_ADDR(reg,name)			\ +	pla	reg,name@pcrel + +#else  #define LOAD_REG_ADDR(reg,name)			\  	addis	reg,r2,name@toc@ha;		\  	addi	reg,reg,name@toc@l +#endif  #ifdef CONFIG_PPC_BOOK3E_64  /* @@ -837,4 +861,12 @@ END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96)  #define BTB_FLUSH(reg)  #endif /* CONFIG_PPC_E500 */ +#if defined(CONFIG_PPC64_ELF_ABI_V1) +#define STACK_FRAME_PARAMS 48 +#elif defined(CONFIG_PPC64_ELF_ABI_V2) +#define STACK_FRAME_PARAMS 32 +#elif defined(CONFIG_PPC32) +#define STACK_FRAME_PARAMS 8 +#endif +  #endif /* _ASM_POWERPC_PPC_ASM_H */ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 1e8b2e04e626..6372e5f55ef0 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -382,8 +382,6 @@  #define SPRN_HIOR	0x137	/* 970 Hypervisor interrupt offset */  #define SPRN_RMOR	0x138	/* Real mode offset register */  #define SPRN_HRMOR	0x139	/* Real mode offset register */ -#define SPRN_HSRR0	0x13A	/* Hypervisor Save/Restore 0 */ -#define SPRN_HSRR1	0x13B	/* Hypervisor Save/Restore 1 */  #define SPRN_ASDR	0x330	/* Access segment descriptor register */  #define SPRN_IC		0x350	/* Virtual Instruction Count */  #define SPRN_VTB	0x351	/* Virtual Time Base */ @@ -417,6 +415,7 @@  #define   FSCR_DSCR	__MASK(FSCR_DSCR_LG)  #define   FSCR_INTR_CAUSE (ASM_CONST(0xFF) << 56)	/* interrupt cause */  #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) @@ -1310,6 +1309,11 @@  #define PVR_VER_E500MC	0x8023  #define PVR_VER_E5500	0x8024  #define PVR_VER_E6500	0x8040 +#define PVR_VER_7450	0x8000 +#define PVR_VER_7455	0x8001 +#define PVR_VER_7447	0x8002 +#define PVR_VER_7447A	0x8003 +#define PVR_VER_7448	0x8004  /*   * For the 8xx processors, all of them report the same PVR family for diff --git a/arch/powerpc/include/asm/rtas-types.h b/arch/powerpc/include/asm/rtas-types.h index f2ad4a96cbc5..9d5b16803cbb 100644 --- a/arch/powerpc/include/asm/rtas-types.h +++ b/arch/powerpc/include/asm/rtas-types.h @@ -2,7 +2,7 @@  #ifndef _ASM_POWERPC_RTAS_TYPES_H  #define _ASM_POWERPC_RTAS_TYPES_H -#include <linux/spinlock_types.h> +#include <linux/compiler_attributes.h>  typedef __be32 rtas_arg_t; @@ -12,7 +12,7 @@ struct rtas_args {  	__be32 nret;  	rtas_arg_t args[16];  	rtas_arg_t *rets;     /* Pointer to return values in args[]. */ -}; +} __aligned(8);  struct rtas_t {  	unsigned long entry;		/* physical address pointer */ diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index 9c00c9c0ca8f..4e1f548c8d37 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h @@ -46,10 +46,15 @@ extern char end_virt_trampolines[];   */  static inline unsigned long kernel_toc_addr(void)  { +#ifdef CONFIG_PPC_KERNEL_PCREL +	BUILD_BUG(); +	return -1UL; +#else  	unsigned long toc_ptr;  	asm volatile("mr %0, 2" : "=r" (toc_ptr));  	return toc_ptr; +#endif  }  static inline int overlaps_interrupt_vector_text(unsigned long start, diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 6c6cb53d7045..aaaa576d0e15 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h @@ -67,7 +67,7 @@ void start_secondary(void *unused);  extern int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us);  extern int smp_send_safe_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us);  extern void smp_send_debugger_break(void); -extern void start_secondary_resume(void); +extern void __noreturn start_secondary_resume(void);  extern void smp_generic_give_timebase(void);  extern void smp_generic_take_timebase(void); diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index af58f1ed3952..bf5dde1a4114 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -45,6 +45,7 @@  #include <linux/cache.h>  #include <asm/processor.h>  #include <asm/accounting.h> +#include <asm/ppc_asm.h>  #define SLB_PRELOAD_NR	16U  /* @@ -175,9 +176,11 @@ static inline bool test_thread_local_flags(unsigned int flags)  #ifdef CONFIG_COMPAT  #define is_32bit_task()	(test_thread_flag(TIF_32BIT))  #define is_tsk_32bit_task(tsk)	(test_tsk_thread_flag(tsk, TIF_32BIT)) +#define clear_tsk_compat_task(tsk) (clear_tsk_thread_flag(p, TIF_32BIT))  #else  #define is_32bit_task()	(IS_ENABLED(CONFIG_PPC32))  #define is_tsk_32bit_task(tsk)	(IS_ENABLED(CONFIG_PPC32)) +#define clear_tsk_compat_task(tsk) do { } while (0)  #endif  #if defined(CONFIG_PPC64) @@ -186,6 +189,43 @@ static inline bool test_thread_local_flags(unsigned int flags)  #define is_elf2_task() (0)  #endif +/* + * Walks up the stack frames to make sure that the specified object is + * entirely contained by a single stack frame. + * + * Returns: + *	GOOD_FRAME	if within a frame + *	BAD_STACK	if placed across a frame boundary (or outside stack) + */ +static inline int arch_within_stack_frames(const void * const stack, +					   const void * const stackend, +					   const void *obj, unsigned long len) +{ +	const void *params; +	const void *frame; + +	params = *(const void * const *)current_stack_pointer + STACK_FRAME_PARAMS; +	frame = **(const void * const * const *)current_stack_pointer; + +	/* +	 * low -----------------------------------------------------------> high +	 * [backchain][metadata][params][local vars][saved registers][backchain] +	 *                      ^------------------------------------^ +	 *                      |  allows copies only in this region | +	 *                      |                                    | +	 *                    params                               frame +	 * The metadata region contains the saved LR, CR etc. +	 */ +	while (stack <= frame && frame < stackend) { +		if (obj + len <= frame) +			return obj >= params ? GOOD_FRAME : BAD_STACK; +		params = frame + STACK_FRAME_PARAMS; +		frame = *(const void * const *)frame; +	} + +	return BAD_STACK; +} +  #endif	/* !__ASSEMBLY__ */  #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 3ddc65c63a49..a2d255aa9627 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -71,14 +71,26 @@ __pu_failed:							\   * because we do not write to any memory gcc knows about, so there   * are no aliasing issues.   */ +/* -mprefixed can generate offsets beyond range, fall back hack */ +#ifdef CONFIG_PPC_KERNEL_PREFIXED +#define __put_user_asm_goto(x, addr, label, op)			\ +	asm_volatile_goto(					\ +		"1:	" op " %0,0(%1)	# put_user\n"		\ +		EX_TABLE(1b, %l2)				\ +		:						\ +		: "r" (x), "b" (addr)				\ +		:						\ +		: label) +#else  #define __put_user_asm_goto(x, addr, label, op)			\  	asm_volatile_goto(					\  		"1:	" op "%U1%X1 %0,%1	# put_user\n"	\  		EX_TABLE(1b, %l2)				\  		:						\ -		: "r" (x), "m<>" (*addr)		\ +		: "r" (x), "m<>" (*addr)			\  		:						\  		: label) +#endif  #ifdef __powerpc64__  #define __put_user_asm2_goto(x, ptr, label)			\ @@ -131,14 +143,26 @@ do {								\  #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT +/* -mprefixed can generate offsets beyond range, fall back hack */ +#ifdef CONFIG_PPC_KERNEL_PREFIXED +#define __get_user_asm_goto(x, addr, label, op)			\ +	asm_volatile_goto(					\ +		"1:	"op" %0,0(%1)	# get_user\n"		\ +		EX_TABLE(1b, %l2)				\ +		: "=r" (x)					\ +		: "b" (addr)					\ +		:						\ +		: label) +#else  #define __get_user_asm_goto(x, addr, label, op)			\  	asm_volatile_goto(					\  		"1:	"op"%U1%X1 %0, %1	# get_user\n"	\  		EX_TABLE(1b, %l2)				\  		: "=r" (x)					\ -		: "m<>" (*addr)				\ +		: "m<>" (*addr)					\  		:						\  		: label) +#endif  #ifdef __powerpc64__  #define __get_user_asm2_goto(x, addr, label)			\ @@ -361,8 +385,6 @@ copy_mc_to_user(void __user *to, const void *from, unsigned long n)  extern long __copy_from_user_flushcache(void *dst, const void __user *src,  		unsigned size); -extern void memcpy_page_flushcache(char *to, struct page *page, size_t offset, -			   size_t len);  static __must_check inline bool user_access_begin(const void __user *ptr, size_t len)  { diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h index 308857123a08..dbc4a5b8d02d 100644 --- a/arch/powerpc/include/uapi/asm/elf.h +++ b/arch/powerpc/include/uapi/asm/elf.h @@ -279,8 +279,12 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[ELF_NVSRHALFREG];  #define R_PPC64_TLSLD		108  #define R_PPC64_TOCSAVE		109 +#define R_PPC64_REL24_NOTOC	116  #define R_PPC64_ENTRY		118 +#define R_PPC64_PCREL34		132 +#define R_PPC64_GOT_PCREL34	133 +  #define R_PPC64_REL16		249  #define R_PPC64_REL16_LO	250  #define R_PPC64_REL16_HI	251 | 
