diff options
Diffstat (limited to 'include/asm-generic')
| -rw-r--r-- | include/asm-generic/atomic-long.h | 58 | ||||
| -rw-r--r-- | include/asm-generic/atomic.h | 47 | ||||
| -rw-r--r-- | include/asm-generic/atomic64.h | 15 | ||||
| -rw-r--r-- | include/asm-generic/barrier.h | 41 | ||||
| -rw-r--r-- | include/asm-generic/cputime_nsecs.h | 2 | ||||
| -rw-r--r-- | include/asm-generic/io.h | 71 | ||||
| -rw-r--r-- | include/asm-generic/iomap.h | 8 | ||||
| -rw-r--r-- | include/asm-generic/mutex-dec.h | 2 | ||||
| -rw-r--r-- | include/asm-generic/mutex-xchg.h | 6 | ||||
| -rw-r--r-- | include/asm-generic/qspinlock.h | 5 | ||||
| -rw-r--r-- | include/asm-generic/rwsem.h | 22 | ||||
| -rw-r--r-- | include/asm-generic/tlb.h | 59 | ||||
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 14 | 
13 files changed, 304 insertions, 46 deletions
| diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h index 5e1f345b58dd..288cc9e96395 100644 --- a/include/asm-generic/atomic-long.h +++ b/include/asm-generic/atomic-long.h @@ -112,6 +112,62 @@ static __always_inline void atomic_long_dec(atomic_long_t *l)  	ATOMIC_LONG_PFX(_dec)(v);  } +#define ATOMIC_LONG_FETCH_OP(op, mo)					\ +static inline long							\ +atomic_long_fetch_##op##mo(long i, atomic_long_t *l)			\ +{									\ +	ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;		\ +									\ +	return (long)ATOMIC_LONG_PFX(_fetch_##op##mo)(i, v);		\ +} + +ATOMIC_LONG_FETCH_OP(add, ) +ATOMIC_LONG_FETCH_OP(add, _relaxed) +ATOMIC_LONG_FETCH_OP(add, _acquire) +ATOMIC_LONG_FETCH_OP(add, _release) +ATOMIC_LONG_FETCH_OP(sub, ) +ATOMIC_LONG_FETCH_OP(sub, _relaxed) +ATOMIC_LONG_FETCH_OP(sub, _acquire) +ATOMIC_LONG_FETCH_OP(sub, _release) +ATOMIC_LONG_FETCH_OP(and, ) +ATOMIC_LONG_FETCH_OP(and, _relaxed) +ATOMIC_LONG_FETCH_OP(and, _acquire) +ATOMIC_LONG_FETCH_OP(and, _release) +ATOMIC_LONG_FETCH_OP(andnot, ) +ATOMIC_LONG_FETCH_OP(andnot, _relaxed) +ATOMIC_LONG_FETCH_OP(andnot, _acquire) +ATOMIC_LONG_FETCH_OP(andnot, _release) +ATOMIC_LONG_FETCH_OP(or, ) +ATOMIC_LONG_FETCH_OP(or, _relaxed) +ATOMIC_LONG_FETCH_OP(or, _acquire) +ATOMIC_LONG_FETCH_OP(or, _release) +ATOMIC_LONG_FETCH_OP(xor, ) +ATOMIC_LONG_FETCH_OP(xor, _relaxed) +ATOMIC_LONG_FETCH_OP(xor, _acquire) +ATOMIC_LONG_FETCH_OP(xor, _release) + +#undef ATOMIC_LONG_FETCH_OP + +#define ATOMIC_LONG_FETCH_INC_DEC_OP(op, mo)					\ +static inline long							\ +atomic_long_fetch_##op##mo(atomic_long_t *l)				\ +{									\ +	ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;		\ +									\ +	return (long)ATOMIC_LONG_PFX(_fetch_##op##mo)(v);		\ +} + +ATOMIC_LONG_FETCH_INC_DEC_OP(inc,) +ATOMIC_LONG_FETCH_INC_DEC_OP(inc, _relaxed) +ATOMIC_LONG_FETCH_INC_DEC_OP(inc, _acquire) +ATOMIC_LONG_FETCH_INC_DEC_OP(inc, _release) +ATOMIC_LONG_FETCH_INC_DEC_OP(dec,) +ATOMIC_LONG_FETCH_INC_DEC_OP(dec, _relaxed) +ATOMIC_LONG_FETCH_INC_DEC_OP(dec, _acquire) +ATOMIC_LONG_FETCH_INC_DEC_OP(dec, _release) + +#undef ATOMIC_LONG_FETCH_INC_DEC_OP +  #define ATOMIC_LONG_OP(op)						\  static __always_inline void						\  atomic_long_##op(long i, atomic_long_t *l)				\ @@ -124,9 +180,9 @@ atomic_long_##op(long i, atomic_long_t *l)				\  ATOMIC_LONG_OP(add)  ATOMIC_LONG_OP(sub)  ATOMIC_LONG_OP(and) +ATOMIC_LONG_OP(andnot)  ATOMIC_LONG_OP(or)  ATOMIC_LONG_OP(xor) -ATOMIC_LONG_OP(andnot)  #undef ATOMIC_LONG_OP diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index 74f1a3704d7a..9ed8b987185b 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -61,6 +61,18 @@ static inline int atomic_##op##_return(int i, atomic_t *v)		\  	return c c_op i;						\  } +#define ATOMIC_FETCH_OP(op, c_op)					\ +static inline int atomic_fetch_##op(int i, atomic_t *v)			\ +{									\ +	int c, old;							\ +									\ +	c = v->counter;							\ +	while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)		\ +		c = old;						\ +									\ +	return c;							\ +} +  #else  #include <linux/irqflags.h> @@ -88,6 +100,20 @@ static inline int atomic_##op##_return(int i, atomic_t *v)		\  	return ret;							\  } +#define ATOMIC_FETCH_OP(op, c_op)					\ +static inline int atomic_fetch_##op(int i, atomic_t *v)			\ +{									\ +	unsigned long flags;						\ +	int ret;							\ +									\ +	raw_local_irq_save(flags);					\ +	ret = v->counter;						\ +	v->counter = v->counter c_op i;					\ +	raw_local_irq_restore(flags);					\ +									\ +	return ret;							\ +} +  #endif /* CONFIG_SMP */  #ifndef atomic_add_return @@ -98,6 +124,26 @@ ATOMIC_OP_RETURN(add, +)  ATOMIC_OP_RETURN(sub, -)  #endif +#ifndef atomic_fetch_add +ATOMIC_FETCH_OP(add, +) +#endif + +#ifndef atomic_fetch_sub +ATOMIC_FETCH_OP(sub, -) +#endif + +#ifndef atomic_fetch_and +ATOMIC_FETCH_OP(and, &) +#endif + +#ifndef atomic_fetch_or +ATOMIC_FETCH_OP(or, |) +#endif + +#ifndef atomic_fetch_xor +ATOMIC_FETCH_OP(xor, ^) +#endif +  #ifndef atomic_and  ATOMIC_OP(and, &)  #endif @@ -110,6 +156,7 @@ ATOMIC_OP(or, |)  ATOMIC_OP(xor, ^)  #endif +#undef ATOMIC_FETCH_OP  #undef ATOMIC_OP_RETURN  #undef ATOMIC_OP diff --git a/include/asm-generic/atomic64.h b/include/asm-generic/atomic64.h index d48e78ccad3d..dad68bf46c77 100644 --- a/include/asm-generic/atomic64.h +++ b/include/asm-generic/atomic64.h @@ -27,16 +27,23 @@ extern void	 atomic64_##op(long long a, atomic64_t *v);  #define ATOMIC64_OP_RETURN(op)						\  extern long long atomic64_##op##_return(long long a, atomic64_t *v); -#define ATOMIC64_OPS(op)	ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op) +#define ATOMIC64_FETCH_OP(op)						\ +extern long long atomic64_fetch_##op(long long a, atomic64_t *v); + +#define ATOMIC64_OPS(op)	ATOMIC64_OP(op) ATOMIC64_OP_RETURN(op) ATOMIC64_FETCH_OP(op)  ATOMIC64_OPS(add)  ATOMIC64_OPS(sub) -ATOMIC64_OP(and) -ATOMIC64_OP(or) -ATOMIC64_OP(xor) +#undef ATOMIC64_OPS +#define ATOMIC64_OPS(op)	ATOMIC64_OP(op) ATOMIC64_FETCH_OP(op) + +ATOMIC64_OPS(and) +ATOMIC64_OPS(or) +ATOMIC64_OPS(xor)  #undef ATOMIC64_OPS +#undef ATOMIC64_FETCH_OP  #undef ATOMIC64_OP_RETURN  #undef ATOMIC64_OP diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h index 1cceca146905..fe297b599b0a 100644 --- a/include/asm-generic/barrier.h +++ b/include/asm-generic/barrier.h @@ -194,7 +194,7 @@ do {									\  })  #endif -#endif +#endif	/* CONFIG_SMP */  /* Barriers for virtual machine guests when talking to an SMP host */  #define virt_mb() __smp_mb() @@ -207,5 +207,44 @@ do {									\  #define virt_store_release(p, v) __smp_store_release(p, v)  #define virt_load_acquire(p) __smp_load_acquire(p) +/** + * smp_acquire__after_ctrl_dep() - Provide ACQUIRE ordering after a control dependency + * + * A control dependency provides a LOAD->STORE order, the additional RMB + * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order, + * aka. (load)-ACQUIRE. + * + * Architectures that do not do load speculation can have this be barrier(). + */ +#ifndef smp_acquire__after_ctrl_dep +#define smp_acquire__after_ctrl_dep()		smp_rmb() +#endif + +/** + * smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering + * @ptr: pointer to the variable to wait on + * @cond: boolean expression to wait for + * + * Equivalent to using smp_load_acquire() on the condition variable but employs + * the control dependency of the wait to reduce the barrier on many platforms. + * + * Due to C lacking lambda expressions we load the value of *ptr into a + * pre-named variable @VAL to be used in @cond. + */ +#ifndef smp_cond_load_acquire +#define smp_cond_load_acquire(ptr, cond_expr) ({		\ +	typeof(ptr) __PTR = (ptr);				\ +	typeof(*ptr) VAL;					\ +	for (;;) {						\ +		VAL = READ_ONCE(*__PTR);			\ +		if (cond_expr)					\ +			break;					\ +		cpu_relax();					\ +	}							\ +	smp_acquire__after_ctrl_dep();				\ +	VAL;							\ +}) +#endif +  #endif /* !__ASSEMBLY__ */  #endif /* __ASM_GENERIC_BARRIER_H */ diff --git a/include/asm-generic/cputime_nsecs.h b/include/asm-generic/cputime_nsecs.h index 0f1c6f315cdc..a84e28e0c634 100644 --- a/include/asm-generic/cputime_nsecs.h +++ b/include/asm-generic/cputime_nsecs.h @@ -50,6 +50,8 @@ typedef u64 __nocast cputime64_t;  	(__force u64)(__ct)  #define nsecs_to_cputime(__nsecs)	\  	(__force cputime_t)(__nsecs) +#define nsecs_to_cputime64(__nsecs)	\ +	(__force cputime64_t)(__nsecs)  /* diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 002b81f6f2bc..7ef015eb3403 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -585,6 +585,16 @@ static inline u32 ioread32(const volatile void __iomem *addr)  }  #endif +#ifdef CONFIG_64BIT +#ifndef ioread64 +#define ioread64 ioread64 +static inline u64 ioread64(const volatile void __iomem *addr) +{ +	return readq(addr); +} +#endif +#endif /* CONFIG_64BIT */ +  #ifndef iowrite8  #define iowrite8 iowrite8  static inline void iowrite8(u8 value, volatile void __iomem *addr) @@ -609,11 +619,21 @@ static inline void iowrite32(u32 value, volatile void __iomem *addr)  }  #endif +#ifdef CONFIG_64BIT +#ifndef iowrite64 +#define iowrite64 iowrite64 +static inline void iowrite64(u64 value, volatile void __iomem *addr) +{ +	writeq(value, addr); +} +#endif +#endif /* CONFIG_64BIT */ +  #ifndef ioread16be  #define ioread16be ioread16be  static inline u16 ioread16be(const volatile void __iomem *addr)  { -	return __be16_to_cpu(__raw_readw(addr)); +	return swab16(readw(addr));  }  #endif @@ -621,15 +641,25 @@ static inline u16 ioread16be(const volatile void __iomem *addr)  #define ioread32be ioread32be  static inline u32 ioread32be(const volatile void __iomem *addr)  { -	return __be32_to_cpu(__raw_readl(addr)); +	return swab32(readl(addr)); +} +#endif + +#ifdef CONFIG_64BIT +#ifndef ioread64be +#define ioread64be ioread64be +static inline u64 ioread64be(const volatile void __iomem *addr) +{ +	return swab64(readq(addr));  }  #endif +#endif /* CONFIG_64BIT */  #ifndef iowrite16be  #define iowrite16be iowrite16be  static inline void iowrite16be(u16 value, void volatile __iomem *addr)  { -	__raw_writew(__cpu_to_be16(value), addr); +	writew(swab16(value), addr);  }  #endif @@ -637,10 +667,20 @@ static inline void iowrite16be(u16 value, void volatile __iomem *addr)  #define iowrite32be iowrite32be  static inline void iowrite32be(u32 value, volatile void __iomem *addr)  { -	__raw_writel(__cpu_to_be32(value), addr); +	writel(swab32(value), addr);  }  #endif +#ifdef CONFIG_64BIT +#ifndef iowrite64be +#define iowrite64be iowrite64be +static inline void iowrite64be(u64 value, volatile void __iomem *addr) +{ +	writeq(swab64(value), addr); +} +#endif +#endif /* CONFIG_64BIT */ +  #ifndef ioread8_rep  #define ioread8_rep ioread8_rep  static inline void ioread8_rep(const volatile void __iomem *addr, void *buffer, @@ -668,6 +708,17 @@ static inline void ioread32_rep(const volatile void __iomem *addr,  }  #endif +#ifdef CONFIG_64BIT +#ifndef ioread64_rep +#define ioread64_rep ioread64_rep +static inline void ioread64_rep(const volatile void __iomem *addr, +				void *buffer, unsigned int count) +{ +	readsq(addr, buffer, count); +} +#endif +#endif /* CONFIG_64BIT */ +  #ifndef iowrite8_rep  #define iowrite8_rep iowrite8_rep  static inline void iowrite8_rep(volatile void __iomem *addr, @@ -697,6 +748,18 @@ static inline void iowrite32_rep(volatile void __iomem *addr,  	writesl(addr, buffer, count);  }  #endif + +#ifdef CONFIG_64BIT +#ifndef iowrite64_rep +#define iowrite64_rep iowrite64_rep +static inline void iowrite64_rep(volatile void __iomem *addr, +				 const void *buffer, +				 unsigned int count) +{ +	writesq(addr, buffer, count); +} +#endif +#endif /* CONFIG_64BIT */  #endif /* CONFIG_GENERIC_IOMAP */  #ifdef __KERNEL__ diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h index d8f8622fa044..650fede33c25 100644 --- a/include/asm-generic/iomap.h +++ b/include/asm-generic/iomap.h @@ -30,12 +30,20 @@ extern unsigned int ioread16(void __iomem *);  extern unsigned int ioread16be(void __iomem *);  extern unsigned int ioread32(void __iomem *);  extern unsigned int ioread32be(void __iomem *); +#ifdef CONFIG_64BIT +extern u64 ioread64(void __iomem *); +extern u64 ioread64be(void __iomem *); +#endif  extern void iowrite8(u8, void __iomem *);  extern void iowrite16(u16, void __iomem *);  extern void iowrite16be(u16, void __iomem *);  extern void iowrite32(u32, void __iomem *);  extern void iowrite32be(u32, void __iomem *); +#ifdef CONFIG_64BIT +extern void iowrite64(u64, void __iomem *); +extern void iowrite64be(u64, void __iomem *); +#endif  /*   * "string" versions of the above. Note that they diff --git a/include/asm-generic/mutex-dec.h b/include/asm-generic/mutex-dec.h index fd694cfd678a..c54829d3de37 100644 --- a/include/asm-generic/mutex-dec.h +++ b/include/asm-generic/mutex-dec.h @@ -80,7 +80,7 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))  static inline int  __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))  { -	if (likely(atomic_cmpxchg_acquire(count, 1, 0) == 1)) +	if (likely(atomic_read(count) == 1 && atomic_cmpxchg_acquire(count, 1, 0) == 1))  		return 1;  	return 0;  } diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h index a6b4a7bd6ac9..3269ec4e195f 100644 --- a/include/asm-generic/mutex-xchg.h +++ b/include/asm-generic/mutex-xchg.h @@ -91,8 +91,12 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))  static inline int  __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))  { -	int prev = atomic_xchg_acquire(count, 0); +	int prev; +	if (atomic_read(count) != 1) +		return 0; + +	prev = atomic_xchg_acquire(count, 0);  	if (unlikely(prev < 0)) {  		/*  		 * The lock was marked contended so we must restore that diff --git a/include/asm-generic/qspinlock.h b/include/asm-generic/qspinlock.h index 05f05f17a7c2..9f0681bf1e87 100644 --- a/include/asm-generic/qspinlock.h +++ b/include/asm-generic/qspinlock.h @@ -111,10 +111,9 @@ static __always_inline void queued_spin_lock(struct qspinlock *lock)  static __always_inline void queued_spin_unlock(struct qspinlock *lock)  {  	/* -	 * smp_mb__before_atomic() in order to guarantee release semantics +	 * unlock() needs release semantics:  	 */ -	smp_mb__before_atomic(); -	atomic_sub(_Q_LOCKED_VAL, &lock->val); +	(void)atomic_sub_return_release(_Q_LOCKED_VAL, &lock->val);  }  #endif diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h index 3fc94a046bf5..5be122e3d326 100644 --- a/include/asm-generic/rwsem.h +++ b/include/asm-generic/rwsem.h @@ -41,8 +41,8 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)  {  	long tmp; -	while ((tmp = sem->count) >= 0) { -		if (tmp == cmpxchg_acquire(&sem->count, tmp, +	while ((tmp = atomic_long_read(&sem->count)) >= 0) { +		if (tmp == atomic_long_cmpxchg_acquire(&sem->count, tmp,  				   tmp + RWSEM_ACTIVE_READ_BIAS)) {  			return 1;  		} @@ -79,7 +79,7 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)  {  	long tmp; -	tmp = cmpxchg_acquire(&sem->count, RWSEM_UNLOCKED_VALUE, +	tmp = atomic_long_cmpxchg_acquire(&sem->count, RWSEM_UNLOCKED_VALUE,  		      RWSEM_ACTIVE_WRITE_BIAS);  	return tmp == RWSEM_UNLOCKED_VALUE;  } @@ -107,14 +107,6 @@ static inline void __up_write(struct rw_semaphore *sem)  }  /* - * implement atomic add functionality - */ -static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) -{ -	atomic_long_add(delta, (atomic_long_t *)&sem->count); -} - -/*   * downgrade write lock to read lock   */  static inline void __downgrade_write(struct rw_semaphore *sem) @@ -134,13 +126,5 @@ static inline void __downgrade_write(struct rw_semaphore *sem)  		rwsem_downgrade_wake(sem);  } -/* - * implement exchange and add functionality - */ -static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) -{ -	return atomic_long_add_return(delta, (atomic_long_t *)&sem->count); -} -  #endif	/* __KERNEL__ */  #endif	/* _ASM_GENERIC_RWSEM_H */ diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index 9dbb739cafa0..c6d667187608 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h @@ -107,6 +107,12 @@ struct mmu_gather {  	struct mmu_gather_batch	local;  	struct page		*__pages[MMU_GATHER_BUNDLE];  	unsigned int		batch_count; +	/* +	 * __tlb_adjust_range  will track the new addr here, +	 * that that we can adjust the range after the flush +	 */ +	unsigned long addr; +	int page_size;  };  #define HAVE_GENERIC_MMU_GATHER @@ -115,23 +121,20 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long  void tlb_flush_mmu(struct mmu_gather *tlb);  void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start,  							unsigned long end); -int __tlb_remove_page(struct mmu_gather *tlb, struct page *page); - -/* tlb_remove_page - *	Similar to __tlb_remove_page but will call tlb_flush_mmu() itself when - *	required. - */ -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) -{ -	if (!__tlb_remove_page(tlb, page)) -		tlb_flush_mmu(tlb); -} +extern bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, +				   int page_size);  static inline void __tlb_adjust_range(struct mmu_gather *tlb,  				      unsigned long address)  {  	tlb->start = min(tlb->start, address);  	tlb->end = max(tlb->end, address + PAGE_SIZE); +	/* +	 * Track the last address with which we adjusted the range. This +	 * will be used later to adjust again after a mmu_flush due to +	 * failed __tlb_remove_page +	 */ +	tlb->addr = address;  }  static inline void __tlb_reset_range(struct mmu_gather *tlb) @@ -144,6 +147,40 @@ static inline void __tlb_reset_range(struct mmu_gather *tlb)  	}  } +static inline void tlb_remove_page_size(struct mmu_gather *tlb, +					struct page *page, int page_size) +{ +	if (__tlb_remove_page_size(tlb, page, page_size)) { +		tlb_flush_mmu(tlb); +		tlb->page_size = page_size; +		__tlb_adjust_range(tlb, tlb->addr); +		__tlb_remove_page_size(tlb, page, page_size); +	} +} + +static bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ +	return __tlb_remove_page_size(tlb, page, PAGE_SIZE); +} + +/* tlb_remove_page + *	Similar to __tlb_remove_page but will call tlb_flush_mmu() itself when + *	required. + */ +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ +	return tlb_remove_page_size(tlb, page, PAGE_SIZE); +} + +static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb, struct page *page) +{ +	/* active->nr should be zero when we call this */ +	VM_BUG_ON_PAGE(tlb->active->nr, page); +	tlb->page_size = PAGE_SIZE; +	__tlb_adjust_range(tlb, tlb->addr); +	return __tlb_remove_page(tlb, page); +} +  /*   * In the case of tlb vma handling, we can optimise these away in the   * case where we're doing a full MM flush.  When we're doing a munmap, diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 6a67ab94b553..54643d1f5af4 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -250,6 +250,14 @@  	VMLINUX_SYMBOL(__end_init_task) = .;  /* + * Allow architectures to handle ro_after_init data on their + * own by defining an empty RO_AFTER_INIT_DATA. + */ +#ifndef RO_AFTER_INIT_DATA +#define RO_AFTER_INIT_DATA *(.data..ro_after_init) +#endif + +/*   * Read only Data   */  #define RO_DATA_SECTION(align)						\ @@ -257,7 +265,7 @@  	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\  		VMLINUX_SYMBOL(__start_rodata) = .;			\  		*(.rodata) *(.rodata.*)					\ -		*(.data..ro_after_init)	/* Read only after init */	\ +		RO_AFTER_INIT_DATA	/* Read only after init */	\  		*(__vermagic)		/* Kernel version magic */	\  		. = ALIGN(8);						\  		VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .;		\ @@ -542,15 +550,19 @@  #define INIT_TEXT							\  	*(.init.text)							\ +	*(.text.startup)						\  	MEM_DISCARD(init.text)  #define EXIT_DATA							\  	*(.exit.data)							\ +	*(.fini_array)							\ +	*(.dtors)							\  	MEM_DISCARD(exit.data)						\  	MEM_DISCARD(exit.rodata)  #define EXIT_TEXT							\  	*(.exit.text)							\ +	*(.text.exit)							\  	MEM_DISCARD(exit.text)  #define EXIT_CALL							\ |