diff mbox series

[v3,2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says

Message ID 1d40783e676e07858be97d881f449ee7ea8adfb1.1633001016.git.christophe.leroy@csgroup.eu (mailing list archive)
State New
Headers show
Series [v3,1/4] mm: Create a new system state and fix core_kernel_text() | expand

Commit Message

Christophe Leroy Sept. 30, 2021, 11:23 a.m. UTC
Commit 7a5da02de8d6 ("locking/lockdep: check for freed initmem in
static_obj()") added arch_is_kernel_initmem_freed() which is supposed
to report whether an object is part of already freed init memory.

For the time being, the generic version of arch_is_kernel_initmem_freed()
always reports 'false', allthough free_initmem() is generically called
on all architectures.

Therefore, change the generic version of arch_is_kernel_initmem_freed()
to check whether free_initmem() has been called. If so, then check
if a given address falls into init memory.

To ease the use of system_state, move it out of line into its only
caller which is lockdep.c

Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v3: Move it out of sections.h into lockdep.c and fix the comment.

v2: Change to using the new SYSTEM_FREEING_INITMEM state
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
 include/asm-generic/sections.h | 14 --------------
 kernel/locking/lockdep.c       | 15 +++++++++++++++
 2 files changed, 15 insertions(+), 14 deletions(-)

Comments

Daniel Axtens Oct. 1, 2021, 7:14 a.m. UTC | #1
>  #ifdef __KERNEL__
> +/*
> + * Check if an address is part of freed initmem. After initmem is freed,
> + * memory can be allocated from it, and such allocations would then have
> + * addresses within the range [_stext, _end].
> + */
> +#ifndef arch_is_kernel_initmem_freed
> +static int arch_is_kernel_initmem_freed(unsigned long addr)
> +{
> +	if (system_state < SYSTEM_FREEING_INITMEM)
> +		return 0;
> +
> +	return init_section_contains((void *)addr, 1);

Is init_section_contains sufficient here?

include/asm-generic/sections.h says:
 * [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
 *                   may be out of this range on some architectures.
 * [_sinittext, _einittext]: contains .init.text.* sections

init_section_contains only checks __init_*:
static inline bool init_section_contains(void *virt, size_t size)
{
	return memory_contains(__init_begin, __init_end, virt, size);
}

Do we need to check against _sinittext and _einittext?

Your proposed generic code will work for powerpc and s390 because those
archs only test against __init_* anyway. I don't know if any platform
actually does place .init.text outside of __init_begin=>__init_end, but
the comment seems to suggest that they could.

Kind regards,
Daniel
Andrew Morton Nov. 4, 2021, 9:44 p.m. UTC | #2
On Fri, 01 Oct 2021 17:14:41 +1000 Daniel Axtens <dja@axtens.net> wrote:

> >  #ifdef __KERNEL__
> > +/*
> > + * Check if an address is part of freed initmem. After initmem is freed,
> > + * memory can be allocated from it, and such allocations would then have
> > + * addresses within the range [_stext, _end].
> > + */
> > +#ifndef arch_is_kernel_initmem_freed
> > +static int arch_is_kernel_initmem_freed(unsigned long addr)
> > +{
> > +	if (system_state < SYSTEM_FREEING_INITMEM)
> > +		return 0;
> > +
> > +	return init_section_contains((void *)addr, 1);
> 
> Is init_section_contains sufficient here?
> 
> include/asm-generic/sections.h says:
>  * [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
>  *                   may be out of this range on some architectures.
>  * [_sinittext, _einittext]: contains .init.text.* sections
> 
> init_section_contains only checks __init_*:
> static inline bool init_section_contains(void *virt, size_t size)
> {
> 	return memory_contains(__init_begin, __init_end, virt, size);
> }
> 
> Do we need to check against _sinittext and _einittext?
> 
> Your proposed generic code will work for powerpc and s390 because those
> archs only test against __init_* anyway. I don't know if any platform
> actually does place .init.text outside of __init_begin=>__init_end, but
> the comment seems to suggest that they could.
> 

Christophe?
Christophe Leroy Nov. 5, 2021, 5:23 p.m. UTC | #3
Le 04/11/2021 à 22:44, Andrew Morton a écrit :
> On Fri, 01 Oct 2021 17:14:41 +1000 Daniel Axtens <dja@axtens.net> wrote:
> 
>>>   #ifdef __KERNEL__
>>> +/*
>>> + * Check if an address is part of freed initmem. After initmem is freed,
>>> + * memory can be allocated from it, and such allocations would then have
>>> + * addresses within the range [_stext, _end].
>>> + */
>>> +#ifndef arch_is_kernel_initmem_freed
>>> +static int arch_is_kernel_initmem_freed(unsigned long addr)
>>> +{
>>> +	if (system_state < SYSTEM_FREEING_INITMEM)
>>> +		return 0;
>>> +
>>> +	return init_section_contains((void *)addr, 1);
>>
>> Is init_section_contains sufficient here?
>>
>> include/asm-generic/sections.h says:
>>   * [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
>>   *                   may be out of this range on some architectures.
>>   * [_sinittext, _einittext]: contains .init.text.* sections
>>
>> init_section_contains only checks __init_*:
>> static inline bool init_section_contains(void *virt, size_t size)
>> {
>> 	return memory_contains(__init_begin, __init_end, virt, size);
>> }
>>
>> Do we need to check against _sinittext and _einittext?
>>
>> Your proposed generic code will work for powerpc and s390 because those
>> archs only test against __init_* anyway. I don't know if any platform
>> actually does place .init.text outside of __init_begin=>__init_end, but
>> the comment seems to suggest that they could.
>>
> 
> Christophe?
> 

Sorry for answering late.

I've been thorugh free_initmem() in each architecture. The only sections 
involved in the freeing actions are [__init_begin, __init_end], so I 
think checking against __init_being, __init_end is enough.

If some architecture has init text outside of this section, then it is 
not freed hence not necessary to check.

Christophe
diff mbox series

Patch

diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index d16302d3eb59..596ab2092289 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -80,20 +80,6 @@  static inline int arch_is_kernel_data(unsigned long addr)
 }
 #endif
 
-/*
- * Check if an address is part of freed initmem. This is needed on architectures
- * with virt == phys kernel mapping, for code that wants to check if an address
- * is part of a static object within [_stext, _end]. After initmem is freed,
- * memory can be allocated from it, and such allocations would then have
- * addresses within the range [_stext, _end].
- */
-#ifndef arch_is_kernel_initmem_freed
-static inline int arch_is_kernel_initmem_freed(unsigned long addr)
-{
-	return 0;
-}
-#endif
-
 /**
  * memory_contains - checks if an object is contained within a memory region
  * @begin: virtual address of the beginning of the memory region
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index bf1c00c881e4..8e118caf835e 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -788,6 +788,21 @@  static int very_verbose(struct lock_class *class)
  * Is this the address of a static object:
  */
 #ifdef __KERNEL__
+/*
+ * Check if an address is part of freed initmem. After initmem is freed,
+ * memory can be allocated from it, and such allocations would then have
+ * addresses within the range [_stext, _end].
+ */
+#ifndef arch_is_kernel_initmem_freed
+static int arch_is_kernel_initmem_freed(unsigned long addr)
+{
+	if (system_state < SYSTEM_FREEING_INITMEM)
+		return 0;
+
+	return init_section_contains((void *)addr, 1);
+}
+#endif
+
 static int static_obj(const void *obj)
 {
 	unsigned long start = (unsigned long) &_stext,