diff mbox series

[10/13] powerpc: Define KMSAN metadata address ranges for vmalloc and ioremap

Message ID 20231214055539.9420-11-nicholas@linux.ibm.com (mailing list archive)
State Changes Requested
Headers show
Series kmsan: Enable on powerpc | expand

Commit Message

Nicholas Miehlbradt Dec. 14, 2023, 5:55 a.m. UTC
Splits the vmalloc region into four. The first quarter is the new
vmalloc region, the second is used to store shadow metadata and the
third is used to store origin metadata. The fourth quarter is unused.

Do the same for the ioremap region.

Module data is stored in the vmalloc region so alias the modules
metadata addresses to the respective vmalloc metadata addresses. Define
MODULES_VADDR and MODULES_END to the start and end of the vmalloc
region.

Since MODULES_VADDR was previously only defined on ppc32 targets checks
for if this macro is defined need to be updated to include
defined(CONFIG_PPC32).

Signed-off-by: Nicholas Miehlbradt <nicholas@linux.ibm.com>
---
 arch/powerpc/include/asm/book3s/64/pgtable.h | 42 ++++++++++++++++++++
 arch/powerpc/kernel/module.c                 |  2 +-
 2 files changed, 43 insertions(+), 1 deletion(-)

Comments

Christophe Leroy Dec. 14, 2023, 9:17 a.m. UTC | #1
Le 14/12/2023 à 06:55, Nicholas Miehlbradt a écrit :
> Splits the vmalloc region into four. The first quarter is the new
> vmalloc region, the second is used to store shadow metadata and the
> third is used to store origin metadata. The fourth quarter is unused.
> 
> Do the same for the ioremap region.
> 
> Module data is stored in the vmalloc region so alias the modules
> metadata addresses to the respective vmalloc metadata addresses. Define
> MODULES_VADDR and MODULES_END to the start and end of the vmalloc
> region.
> 
> Since MODULES_VADDR was previously only defined on ppc32 targets checks
> for if this macro is defined need to be updated to include
> defined(CONFIG_PPC32).

Why ?

In your case MODULES_VADDR is above PAGE_OFFSET so there should be no 
difference.

Christophe

> 
> Signed-off-by: Nicholas Miehlbradt <nicholas@linux.ibm.com>
> ---
>   arch/powerpc/include/asm/book3s/64/pgtable.h | 42 ++++++++++++++++++++
>   arch/powerpc/kernel/module.c                 |  2 +-
>   2 files changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
> index cb77eddca54b..b3a02b8d96e3 100644
> --- a/arch/powerpc/include/asm/book3s/64/pgtable.h
> +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
> @@ -249,7 +249,38 @@ enum pgtable_index {
>   extern unsigned long __vmalloc_start;
>   extern unsigned long __vmalloc_end;
>   #define VMALLOC_START	__vmalloc_start
> +
> +#ifndef CONFIG_KMSAN
>   #define VMALLOC_END	__vmalloc_end
> +#else
> +/*
> + * In KMSAN builds vmalloc area is four times smaller, and the remaining 3/4
> + * are used to keep the metadata for virtual pages. The memory formerly
> + * belonging to vmalloc area is now laid out as follows:
> + *
> + * 1st quarter: VMALLOC_START to VMALLOC_END - new vmalloc area
> + * 2nd quarter: KMSAN_VMALLOC_SHADOW_START to
> + *              KMSAN_VMALLOC_SHADOW_START+VMALLOC_LEN - vmalloc area shadow
> + * 3rd quarter: KMSAN_VMALLOC_ORIGIN_START to
> + *              KMSAN_VMALLOC_ORIGIN_START+VMALLOC_LEN - vmalloc area origins
> + * 4th quarter: unused
> + */
> +#define VMALLOC_LEN ((__vmalloc_end - __vmalloc_start) >> 2)
> +#define VMALLOC_END (VMALLOC_START + VMALLOC_LEN)
> +
> +#define KMSAN_VMALLOC_SHADOW_START VMALLOC_END
> +#define KMSAN_VMALLOC_ORIGIN_START (VMALLOC_END + VMALLOC_LEN)
> +
> +/*
> + * Module metadata is stored in the corresponding vmalloc metadata regions
> + */
> +#define KMSAN_MODULES_SHADOW_START	KMSAN_VMALLOC_SHADOW_START
> +#define KMSAN_MODULES_ORIGIN_START	KMSAN_VMALLOC_ORIGIN_START
> +#endif /* CONFIG_KMSAN */
> +
> +#define MODULES_VADDR VMALLOC_START
> +#define MODULES_END VMALLOC_END
> +#define MODULES_LEN		(MODULES_END - MODULES_VADDR)
>   
>   static inline unsigned int ioremap_max_order(void)
>   {
> @@ -264,7 +295,18 @@ extern unsigned long __kernel_io_start;
>   extern unsigned long __kernel_io_end;
>   #define KERN_VIRT_START __kernel_virt_start
>   #define KERN_IO_START  __kernel_io_start
> +#ifndef CONFIG_KMSAN
>   #define KERN_IO_END __kernel_io_end
> +#else
> +/*
> + * In KMSAN builds IO space is 4 times smaller, the remaining space is used to
> + * store metadata. See comment for vmalloc regions above.
> + */
> +#define KERN_IO_LEN             ((__kernel_io_end - __kernel_io_start) >> 2)
> +#define KERN_IO_END             (KERN_IO_START + KERN_IO_LEN)
> +#define KERN_IO_SHADOW_START    KERN_IO_END
> +#define KERN_IO_ORIGIN_START    (KERN_IO_SHADOW_START + KERN_IO_LEN)
> +#endif /* !CONFIG_KMSAN */
>   
>   extern struct page *vmemmap;
>   extern unsigned long pci_io_base;
> diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
> index f6d6ae0a1692..5043b959ad4d 100644
> --- a/arch/powerpc/kernel/module.c
> +++ b/arch/powerpc/kernel/module.c
> @@ -107,7 +107,7 @@ __module_alloc(unsigned long size, unsigned long start, unsigned long end, bool
>   
>   void *module_alloc(unsigned long size)
>   {
> -#ifdef MODULES_VADDR
> +#if defined(MODULES_VADDR) && defined(CONFIG_PPC32)
>   	unsigned long limit = (unsigned long)_etext - SZ_32M;
>   	void *ptr = NULL;
>
Aneesh Kumar K.V Dec. 15, 2023, 9:27 a.m. UTC | #2
Nicholas Miehlbradt <nicholas@linux.ibm.com> writes:

> Splits the vmalloc region into four. The first quarter is the new
> vmalloc region, the second is used to store shadow metadata and the
> third is used to store origin metadata. The fourth quarter is unused.
>

Do we support KMSAN for both hash and radix? If hash is not supported
can we then using radix.h for these changes?

> Do the same for the ioremap region.
>
> Module data is stored in the vmalloc region so alias the modules
> metadata addresses to the respective vmalloc metadata addresses. Define
> MODULES_VADDR and MODULES_END to the start and end of the vmalloc
> region.
>
> Since MODULES_VADDR was previously only defined on ppc32 targets checks
> for if this macro is defined need to be updated to include
> defined(CONFIG_PPC32).

-aneesh
Nicholas Miehlbradt Jan. 10, 2024, 3:54 a.m. UTC | #3
On 14/12/2023 8:17 pm, Christophe Leroy wrote:
> 
> 
> Le 14/12/2023 à 06:55, Nicholas Miehlbradt a écrit :
>> Splits the vmalloc region into four. The first quarter is the new
>> vmalloc region, the second is used to store shadow metadata and the
>> third is used to store origin metadata. The fourth quarter is unused.
>>
>> Do the same for the ioremap region.
>>
>> Module data is stored in the vmalloc region so alias the modules
>> metadata addresses to the respective vmalloc metadata addresses. Define
>> MODULES_VADDR and MODULES_END to the start and end of the vmalloc
>> region.
>>
>> Since MODULES_VADDR was previously only defined on ppc32 targets checks
>> for if this macro is defined need to be updated to include
>> defined(CONFIG_PPC32).
> 
> Why ?
> 
> In your case MODULES_VADDR is above PAGE_OFFSET so there should be no
> difference.
> 
> Christophe
> 
On 64 bit builds the BUILD_BUG always triggers since MODULES_VADDR 
expands to __vmalloc_start which is defined in a different translation 
unit. I can restrict the #ifdef CONFIG_PPC32 to just around the 
BUILD_BUG since as you pointed out there is no difference otherwise.
>>
>> Signed-off-by: Nicholas Miehlbradt <nicholas@linux.ibm.com>
>> ---
>>    arch/powerpc/include/asm/book3s/64/pgtable.h | 42 ++++++++++++++++++++
>>    arch/powerpc/kernel/module.c                 |  2 +-
>>    2 files changed, 43 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
>> index cb77eddca54b..b3a02b8d96e3 100644
>> --- a/arch/powerpc/include/asm/book3s/64/pgtable.h
>> +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
>> @@ -249,7 +249,38 @@ enum pgtable_index {
>>    extern unsigned long __vmalloc_start;
>>    extern unsigned long __vmalloc_end;
>>    #define VMALLOC_START	__vmalloc_start
>> +
>> +#ifndef CONFIG_KMSAN
>>    #define VMALLOC_END	__vmalloc_end
>> +#else
>> +/*
>> + * In KMSAN builds vmalloc area is four times smaller, and the remaining 3/4
>> + * are used to keep the metadata for virtual pages. The memory formerly
>> + * belonging to vmalloc area is now laid out as follows:
>> + *
>> + * 1st quarter: VMALLOC_START to VMALLOC_END - new vmalloc area
>> + * 2nd quarter: KMSAN_VMALLOC_SHADOW_START to
>> + *              KMSAN_VMALLOC_SHADOW_START+VMALLOC_LEN - vmalloc area shadow
>> + * 3rd quarter: KMSAN_VMALLOC_ORIGIN_START to
>> + *              KMSAN_VMALLOC_ORIGIN_START+VMALLOC_LEN - vmalloc area origins
>> + * 4th quarter: unused
>> + */
>> +#define VMALLOC_LEN ((__vmalloc_end - __vmalloc_start) >> 2)
>> +#define VMALLOC_END (VMALLOC_START + VMALLOC_LEN)
>> +
>> +#define KMSAN_VMALLOC_SHADOW_START VMALLOC_END
>> +#define KMSAN_VMALLOC_ORIGIN_START (VMALLOC_END + VMALLOC_LEN)
>> +
>> +/*
>> + * Module metadata is stored in the corresponding vmalloc metadata regions
>> + */
>> +#define KMSAN_MODULES_SHADOW_START	KMSAN_VMALLOC_SHADOW_START
>> +#define KMSAN_MODULES_ORIGIN_START	KMSAN_VMALLOC_ORIGIN_START
>> +#endif /* CONFIG_KMSAN */
>> +
>> +#define MODULES_VADDR VMALLOC_START
>> +#define MODULES_END VMALLOC_END
>> +#define MODULES_LEN		(MODULES_END - MODULES_VADDR)
>>    
>>    static inline unsigned int ioremap_max_order(void)
>>    {
>> @@ -264,7 +295,18 @@ extern unsigned long __kernel_io_start;
>>    extern unsigned long __kernel_io_end;
>>    #define KERN_VIRT_START __kernel_virt_start
>>    #define KERN_IO_START  __kernel_io_start
>> +#ifndef CONFIG_KMSAN
>>    #define KERN_IO_END __kernel_io_end
>> +#else
>> +/*
>> + * In KMSAN builds IO space is 4 times smaller, the remaining space is used to
>> + * store metadata. See comment for vmalloc regions above.
>> + */
>> +#define KERN_IO_LEN             ((__kernel_io_end - __kernel_io_start) >> 2)
>> +#define KERN_IO_END             (KERN_IO_START + KERN_IO_LEN)
>> +#define KERN_IO_SHADOW_START    KERN_IO_END
>> +#define KERN_IO_ORIGIN_START    (KERN_IO_SHADOW_START + KERN_IO_LEN)
>> +#endif /* !CONFIG_KMSAN */
>>    
>>    extern struct page *vmemmap;
>>    extern unsigned long pci_io_base;
>> diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
>> index f6d6ae0a1692..5043b959ad4d 100644
>> --- a/arch/powerpc/kernel/module.c
>> +++ b/arch/powerpc/kernel/module.c
>> @@ -107,7 +107,7 @@ __module_alloc(unsigned long size, unsigned long start, unsigned long end, bool
>>    
>>    void *module_alloc(unsigned long size)
>>    {
>> -#ifdef MODULES_VADDR
>> +#if defined(MODULES_VADDR) && defined(CONFIG_PPC32)
>>    	unsigned long limit = (unsigned long)_etext - SZ_32M;
>>    	void *ptr = NULL;
>>
diff mbox series

Patch

diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index cb77eddca54b..b3a02b8d96e3 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -249,7 +249,38 @@  enum pgtable_index {
 extern unsigned long __vmalloc_start;
 extern unsigned long __vmalloc_end;
 #define VMALLOC_START	__vmalloc_start
+
+#ifndef CONFIG_KMSAN
 #define VMALLOC_END	__vmalloc_end
+#else
+/*
+ * In KMSAN builds vmalloc area is four times smaller, and the remaining 3/4
+ * are used to keep the metadata for virtual pages. The memory formerly
+ * belonging to vmalloc area is now laid out as follows:
+ *
+ * 1st quarter: VMALLOC_START to VMALLOC_END - new vmalloc area
+ * 2nd quarter: KMSAN_VMALLOC_SHADOW_START to
+ *              KMSAN_VMALLOC_SHADOW_START+VMALLOC_LEN - vmalloc area shadow
+ * 3rd quarter: KMSAN_VMALLOC_ORIGIN_START to
+ *              KMSAN_VMALLOC_ORIGIN_START+VMALLOC_LEN - vmalloc area origins
+ * 4th quarter: unused
+ */
+#define VMALLOC_LEN ((__vmalloc_end - __vmalloc_start) >> 2)
+#define VMALLOC_END (VMALLOC_START + VMALLOC_LEN)
+
+#define KMSAN_VMALLOC_SHADOW_START VMALLOC_END
+#define KMSAN_VMALLOC_ORIGIN_START (VMALLOC_END + VMALLOC_LEN)
+
+/*
+ * Module metadata is stored in the corresponding vmalloc metadata regions
+ */
+#define KMSAN_MODULES_SHADOW_START	KMSAN_VMALLOC_SHADOW_START
+#define KMSAN_MODULES_ORIGIN_START	KMSAN_VMALLOC_ORIGIN_START
+#endif /* CONFIG_KMSAN */
+
+#define MODULES_VADDR VMALLOC_START
+#define MODULES_END VMALLOC_END
+#define MODULES_LEN		(MODULES_END - MODULES_VADDR)
 
 static inline unsigned int ioremap_max_order(void)
 {
@@ -264,7 +295,18 @@  extern unsigned long __kernel_io_start;
 extern unsigned long __kernel_io_end;
 #define KERN_VIRT_START __kernel_virt_start
 #define KERN_IO_START  __kernel_io_start
+#ifndef CONFIG_KMSAN
 #define KERN_IO_END __kernel_io_end
+#else
+/*
+ * In KMSAN builds IO space is 4 times smaller, the remaining space is used to
+ * store metadata. See comment for vmalloc regions above.
+ */
+#define KERN_IO_LEN             ((__kernel_io_end - __kernel_io_start) >> 2)
+#define KERN_IO_END             (KERN_IO_START + KERN_IO_LEN)
+#define KERN_IO_SHADOW_START    KERN_IO_END
+#define KERN_IO_ORIGIN_START    (KERN_IO_SHADOW_START + KERN_IO_LEN)
+#endif /* !CONFIG_KMSAN */
 
 extern struct page *vmemmap;
 extern unsigned long pci_io_base;
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index f6d6ae0a1692..5043b959ad4d 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -107,7 +107,7 @@  __module_alloc(unsigned long size, unsigned long start, unsigned long end, bool
 
 void *module_alloc(unsigned long size)
 {
-#ifdef MODULES_VADDR
+#if defined(MODULES_VADDR) && defined(CONFIG_PPC32)
 	unsigned long limit = (unsigned long)_etext - SZ_32M;
 	void *ptr = NULL;