linux-arch.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 1/4] mm: Create a new system state and fix core_kernel_text()
@ 2021-09-30 11:23 Christophe Leroy
  2021-09-30 11:23 ` [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says Christophe Leroy
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Christophe Leroy @ 2021-09-30 11:23 UTC (permalink / raw)
  To: Andrew Morton, arnd
  Cc: Christophe Leroy, linux-kernel, linux-mm, linux-s390,
	linuxppc-dev, linux-arch, Gerald Schaefer, Kefeng Wang

core_kernel_text() considers that until system_state in at least
SYSTEM_RUNNING, init memory is valid.

But init memory is freed a few lines before setting SYSTEM_RUNNING,
so we have a small period of time when core_kernel_text() is wrong.

Create an intermediate system state called SYSTEM_FREEING_INIT that
is set before starting freeing init memory, and use it in
core_kernel_text() to report init memory invalid earlier.

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: No change
v2: New
---
 include/linux/kernel.h | 1 +
 init/main.c            | 2 ++
 kernel/extable.c       | 2 +-
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2776423a587e..471bc0593679 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -248,6 +248,7 @@ extern bool early_boot_irqs_disabled;
 extern enum system_states {
 	SYSTEM_BOOTING,
 	SYSTEM_SCHEDULING,
+	SYSTEM_FREEING_INITMEM,
 	SYSTEM_RUNNING,
 	SYSTEM_HALT,
 	SYSTEM_POWER_OFF,
diff --git a/init/main.c b/init/main.c
index 3f7216934441..c457d393fdd4 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1505,6 +1505,8 @@ static int __ref kernel_init(void *unused)
 	kernel_init_freeable();
 	/* need to finish all async __init code before freeing the memory */
 	async_synchronize_full();
+
+	system_state = SYSTEM_FREEING_INITMEM;
 	kprobe_free_init_mem();
 	ftrace_free_init_mem();
 	kgdb_free_init_mem();
diff --git a/kernel/extable.c b/kernel/extable.c
index b0ea5eb0c3b4..290661f68e6b 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -76,7 +76,7 @@ int notrace core_kernel_text(unsigned long addr)
 	    addr < (unsigned long)_etext)
 		return 1;
 
-	if (system_state < SYSTEM_RUNNING &&
+	if (system_state < SYSTEM_FREEING_INITMEM &&
 	    init_kernel_text(addr))
 		return 1;
 	return 0;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says
  2021-09-30 11:23 [PATCH v3 1/4] mm: Create a new system state and fix core_kernel_text() Christophe Leroy
@ 2021-09-30 11:23 ` Christophe Leroy
  2021-10-01  7:14   ` Daniel Axtens
  2021-09-30 11:23 ` [PATCH v3 3/4] powerpc: Use generic version of arch_is_kernel_initmem_freed() Christophe Leroy
  2021-09-30 11:23 ` [PATCH v3 4/4] s390: " Christophe Leroy
  2 siblings, 1 reply; 7+ messages in thread
From: Christophe Leroy @ 2021-09-30 11:23 UTC (permalink / raw)
  To: Andrew Morton, arnd
  Cc: Christophe Leroy, linux-kernel, linux-mm, linux-s390,
	linuxppc-dev, linux-arch, Gerald Schaefer, Kefeng Wang

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(-)

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,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/4] powerpc: Use generic version of arch_is_kernel_initmem_freed()
  2021-09-30 11:23 [PATCH v3 1/4] mm: Create a new system state and fix core_kernel_text() Christophe Leroy
  2021-09-30 11:23 ` [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says Christophe Leroy
@ 2021-09-30 11:23 ` Christophe Leroy
  2021-09-30 11:23 ` [PATCH v3 4/4] s390: " Christophe Leroy
  2 siblings, 0 replies; 7+ messages in thread
From: Christophe Leroy @ 2021-09-30 11:23 UTC (permalink / raw)
  To: Andrew Morton, arnd
  Cc: Christophe Leroy, linux-kernel, linux-mm, linux-s390,
	linuxppc-dev, linux-arch, Kefeng Wang

Generic version of arch_is_kernel_initmem_freed() now does the same
as powerpc version.

Remove the powerpc version.

Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v3: No change
v2: No change
---
 arch/powerpc/include/asm/sections.h | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
index 6e4af4492a14..79cb7a25a5fb 100644
--- a/arch/powerpc/include/asm/sections.h
+++ b/arch/powerpc/include/asm/sections.h
@@ -6,21 +6,8 @@
 #include <linux/elf.h>
 #include <linux/uaccess.h>
 
-#define arch_is_kernel_initmem_freed arch_is_kernel_initmem_freed
-
 #include <asm-generic/sections.h>
 
-extern bool init_mem_is_free;
-
-static inline int arch_is_kernel_initmem_freed(unsigned long addr)
-{
-	if (!init_mem_is_free)
-		return 0;
-
-	return addr >= (unsigned long)__init_begin &&
-		addr < (unsigned long)__init_end;
-}
-
 extern char __head_end[];
 
 #ifdef __powerpc64__
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 4/4] s390: Use generic version of arch_is_kernel_initmem_freed()
  2021-09-30 11:23 [PATCH v3 1/4] mm: Create a new system state and fix core_kernel_text() Christophe Leroy
  2021-09-30 11:23 ` [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says Christophe Leroy
  2021-09-30 11:23 ` [PATCH v3 3/4] powerpc: Use generic version of arch_is_kernel_initmem_freed() Christophe Leroy
@ 2021-09-30 11:23 ` Christophe Leroy
  2 siblings, 0 replies; 7+ messages in thread
From: Christophe Leroy @ 2021-09-30 11:23 UTC (permalink / raw)
  To: Andrew Morton, arnd
  Cc: Christophe Leroy, linux-kernel, linux-mm, linux-s390,
	linuxppc-dev, linux-arch, Gerald Schaefer, Kefeng Wang,
	Heiko Carstens

Generic version of arch_is_kernel_initmem_freed() now does the same
as s390 version.

Remove the s390 version.

Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
v3: No change
v2: No change
---
 arch/s390/include/asm/sections.h | 12 ------------
 arch/s390/mm/init.c              |  3 ---
 2 files changed, 15 deletions(-)

diff --git a/arch/s390/include/asm/sections.h b/arch/s390/include/asm/sections.h
index 85881dd48022..3fecaa4e8b74 100644
--- a/arch/s390/include/asm/sections.h
+++ b/arch/s390/include/asm/sections.h
@@ -2,20 +2,8 @@
 #ifndef _S390_SECTIONS_H
 #define _S390_SECTIONS_H
 
-#define arch_is_kernel_initmem_freed arch_is_kernel_initmem_freed
-
 #include <asm-generic/sections.h>
 
-extern bool initmem_freed;
-
-static inline int arch_is_kernel_initmem_freed(unsigned long addr)
-{
-	if (!initmem_freed)
-		return 0;
-	return addr >= (unsigned long)__init_begin &&
-	       addr < (unsigned long)__init_end;
-}
-
 /*
  * .boot.data section contains variables "shared" between the decompressor and
  * the decompressed kernel. The decompressor will store values in them, and
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index a04faf49001a..8c6f258a6183 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -58,8 +58,6 @@ unsigned long empty_zero_page, zero_page_mask;
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(zero_page_mask);
 
-bool initmem_freed;
-
 static void __init setup_zero_pages(void)
 {
 	unsigned int order;
@@ -214,7 +212,6 @@ void __init mem_init(void)
 
 void free_initmem(void)
 {
-	initmem_freed = true;
 	__set_memory((unsigned long)_sinittext,
 		     (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT,
 		     SET_MEMORY_RW | SET_MEMORY_NX);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says
  2021-09-30 11:23 ` [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says Christophe Leroy
@ 2021-10-01  7:14   ` Daniel Axtens
  2021-11-04 21:44     ` Andrew Morton
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Axtens @ 2021-10-01  7:14 UTC (permalink / raw)
  To: Christophe Leroy, Andrew Morton, arnd
  Cc: linux-arch, linux-s390, Kefeng Wang, linux-kernel, linux-mm,
	Gerald Schaefer, linuxppc-dev

>  #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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says
  2021-10-01  7:14   ` Daniel Axtens
@ 2021-11-04 21:44     ` Andrew Morton
  2021-11-05 17:23       ` Christophe Leroy
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2021-11-04 21:44 UTC (permalink / raw)
  To: Daniel Axtens
  Cc: Christophe Leroy, arnd, linux-arch, linux-s390, Kefeng Wang,
	linux-kernel, linux-mm, Gerald Schaefer, linuxppc-dev

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?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says
  2021-11-04 21:44     ` Andrew Morton
@ 2021-11-05 17:23       ` Christophe Leroy
  0 siblings, 0 replies; 7+ messages in thread
From: Christophe Leroy @ 2021-11-05 17:23 UTC (permalink / raw)
  To: Andrew Morton, Daniel Axtens
  Cc: arnd, linux-arch, linux-s390, Kefeng Wang, linux-kernel,
	linux-mm, Gerald Schaefer, linuxppc-dev



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

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-11-05 17:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-30 11:23 [PATCH v3 1/4] mm: Create a new system state and fix core_kernel_text() Christophe Leroy
2021-09-30 11:23 ` [PATCH v3 2/4] mm: Make generic arch_is_kernel_initmem_freed() do what it says Christophe Leroy
2021-10-01  7:14   ` Daniel Axtens
2021-11-04 21:44     ` Andrew Morton
2021-11-05 17:23       ` Christophe Leroy
2021-09-30 11:23 ` [PATCH v3 3/4] powerpc: Use generic version of arch_is_kernel_initmem_freed() Christophe Leroy
2021-09-30 11:23 ` [PATCH v3 4/4] s390: " Christophe Leroy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).