* [PATCH 0/3] mips highmem fixes
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
There are currently a few incorrect assumptions made about the location
and alignment of fixed memory mappings that lead to random crashes when
using highmem with large (>4k) pages
Marcin Nowakowski (3):
MIPS: mm: fixed mappings: correct initialisation
MIPS: highmem: ensure that we don't use more than one page for PTEs
MIPS: mm: adjust PKMAP location
arch/mips/include/asm/highmem.h | 5 +++++
arch/mips/include/asm/pgtable-32.h | 7 ++++++-
arch/mips/mm/pgtable-32.c | 6 +++---
3 files changed, 14 insertions(+), 4 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] MIPS: mm: fixed mappings: correct initialisation
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
fixrange_init operates at PMD-granularity and expects the addresses to
be PMD-size aligned, but currently that might not be the case for
PKMAP_BASE unless it is defined properly, so ensure a correct alignment
is used before passing the address to fixrange_init.
fixed mappings: only align the start address that is passed to
fixrange_init rather than the value before adding the size, as we may
end up with uninitialised upper part of the range.
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
---
arch/mips/mm/pgtable-32.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index adc6911..b19a3c5 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -51,15 +51,15 @@ void __init pagetable_init(void)
/*
* Fixed mappings:
*/
- vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
- fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
+ fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, pgd_base);
#ifdef CONFIG_HIGHMEM
/*
* Permanent kmaps:
*/
vaddr = PKMAP_BASE;
- fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+ fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
pgd = swapper_pg_dir + __pgd_offset(vaddr);
pud = pud_offset(pgd, vaddr);
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 1/3] MIPS: mm: fixed mappings: correct initialisation
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
fixrange_init operates at PMD-granularity and expects the addresses to
be PMD-size aligned, but currently that might not be the case for
PKMAP_BASE unless it is defined properly, so ensure a correct alignment
is used before passing the address to fixrange_init.
fixed mappings: only align the start address that is passed to
fixrange_init rather than the value before adding the size, as we may
end up with uninitialised upper part of the range.
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
---
arch/mips/mm/pgtable-32.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c
index adc6911..b19a3c5 100644
--- a/arch/mips/mm/pgtable-32.c
+++ b/arch/mips/mm/pgtable-32.c
@@ -51,15 +51,15 @@ void __init pagetable_init(void)
/*
* Fixed mappings:
*/
- vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
- fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
+ fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, pgd_base);
#ifdef CONFIG_HIGHMEM
/*
* Permanent kmaps:
*/
vaddr = PKMAP_BASE;
- fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+ fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
pgd = swapper_pg_dir + __pgd_offset(vaddr);
pud = pud_offset(pgd, vaddr);
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] MIPS: highmem: ensure that we don't use more than one page for PTEs
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
All PTEs used by PKMAP should be allocated in a contiguous memory area,
but we do not currently have a mechanism to enforce that, so ensure that
we don't try to allocate more entries than would fit in a single page.
Current fixed value of 1024 would not work with XPA enabled when
sizeof(pte_t)==8 and we need two pages to store pte tables.
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
---
arch/mips/include/asm/highmem.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index d34536e..279b6d1 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -35,7 +35,12 @@ extern pte_t *pkmap_page_table;
* easily, subsequent pte tables have to be allocated in one physical
* chunk of RAM.
*/
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define LAST_PKMAP 512
+#else
#define LAST_PKMAP 1024
+#endif
+
#define LAST_PKMAP_MASK (LAST_PKMAP-1)
#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] MIPS: highmem: ensure that we don't use more than one page for PTEs
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
All PTEs used by PKMAP should be allocated in a contiguous memory area,
but we do not currently have a mechanism to enforce that, so ensure that
we don't try to allocate more entries than would fit in a single page.
Current fixed value of 1024 would not work with XPA enabled when
sizeof(pte_t)==8 and we need two pages to store pte tables.
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
---
arch/mips/include/asm/highmem.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index d34536e..279b6d1 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -35,7 +35,12 @@ extern pte_t *pkmap_page_table;
* easily, subsequent pte tables have to be allocated in one physical
* chunk of RAM.
*/
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define LAST_PKMAP 512
+#else
#define LAST_PKMAP 1024
+#endif
+
#define LAST_PKMAP_MASK (LAST_PKMAP-1)
#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/3] MIPS: mm: adjust PKMAP location
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
Space reserved for PKMap should span from PKMAP_BASE to FIXADDR_START.
For large page sizes this is not the case as eg. for 64k pages the range
currently defined is from 0xfe000000 to 0x102000000(!!) which obviously
isn't right.
Remove the hardcoded location and set the BASE address as an offset from
FIXADDR_START.
Since all PKMAP ptes have to be placed in a contiguous memory, ensure
that this is the case by placing them all in a single page. This is
achieved by aligning the end address to pkmap pages count pages.
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
---
arch/mips/include/asm/pgtable-32.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h
index 6f94bed..74afe8c 100644
--- a/arch/mips/include/asm/pgtable-32.h
+++ b/arch/mips/include/asm/pgtable-32.h
@@ -19,6 +19,10 @@
#define __ARCH_USE_5LEVEL_HACK
#include <asm-generic/pgtable-nopmd.h>
+#ifdef CONFIG_HIGHMEM
+#include <asm/highmem.h>
+#endif
+
extern int temp_tlb_entry;
/*
@@ -62,7 +66,8 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
#define VMALLOC_START MAP_BASE
-#define PKMAP_BASE (0xfe000000UL)
+#define PKMAP_END ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1))
+#define PKMAP_BASE (PKMAP_END - PAGE_SIZE * LAST_PKMAP)
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/3] MIPS: mm: adjust PKMAP location
@ 2017-04-11 7:00 ` Marcin Nowakowski
0 siblings, 0 replies; 9+ messages in thread
From: Marcin Nowakowski @ 2017-04-11 7:00 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, Marcin Nowakowski
Space reserved for PKMap should span from PKMAP_BASE to FIXADDR_START.
For large page sizes this is not the case as eg. for 64k pages the range
currently defined is from 0xfe000000 to 0x102000000(!!) which obviously
isn't right.
Remove the hardcoded location and set the BASE address as an offset from
FIXADDR_START.
Since all PKMAP ptes have to be placed in a contiguous memory, ensure
that this is the case by placing them all in a single page. This is
achieved by aligning the end address to pkmap pages count pages.
Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
---
arch/mips/include/asm/pgtable-32.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h
index 6f94bed..74afe8c 100644
--- a/arch/mips/include/asm/pgtable-32.h
+++ b/arch/mips/include/asm/pgtable-32.h
@@ -19,6 +19,10 @@
#define __ARCH_USE_5LEVEL_HACK
#include <asm-generic/pgtable-nopmd.h>
+#ifdef CONFIG_HIGHMEM
+#include <asm/highmem.h>
+#endif
+
extern int temp_tlb_entry;
/*
@@ -62,7 +66,8 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
#define VMALLOC_START MAP_BASE
-#define PKMAP_BASE (0xfe000000UL)
+#define PKMAP_END ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1))
+#define PKMAP_BASE (PKMAP_END - PAGE_SIZE * LAST_PKMAP)
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] MIPS: mm: adjust PKMAP location
2017-04-11 7:00 ` Marcin Nowakowski
(?)
@ 2017-04-11 9:49 ` Sergei Shtylyov
-1 siblings, 0 replies; 9+ messages in thread
From: Sergei Shtylyov @ 2017-04-11 9:49 UTC (permalink / raw)
To: Marcin Nowakowski, Ralf Baechle; +Cc: linux-mips
Hello!
On 4/11/2017 10:00 AM, Marcin Nowakowski wrote:
> Space reserved for PKMap should span from PKMAP_BASE to FIXADDR_START.
> For large page sizes this is not the case as eg. for 64k pages the range
> currently defined is from 0xfe000000 to 0x102000000(!!) which obviously
> isn't right.
> Remove the hardcoded location and set the BASE address as an offset from
> FIXADDR_START.
>
> Since all PKMAP ptes have to be placed in a contiguous memory, ensure
PTEs?
> that this is the case by placing them all in a single page. This is
> achieved by aligning the end address to pkmap pages count pages.
>
> Signed-off-by: Marcin Nowakowski <marcin.nowakowski@imgtec.com>
> ---
> arch/mips/include/asm/pgtable-32.h | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h
> index 6f94bed..74afe8c 100644
> --- a/arch/mips/include/asm/pgtable-32.h
> +++ b/arch/mips/include/asm/pgtable-32.h
> @@ -19,6 +19,10 @@
> #define __ARCH_USE_5LEVEL_HACK
> #include <asm-generic/pgtable-nopmd.h>
>
> +#ifdef CONFIG_HIGHMEM
> +#include <asm/highmem.h>
> +#endif
> +
> extern int temp_tlb_entry;
>
> /*
> @@ -62,7 +66,8 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
>
> #define VMALLOC_START MAP_BASE
>
> -#define PKMAP_BASE (0xfe000000UL)
> +#define PKMAP_END ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1))
Why parens around FIXADDR_START?
Also could you be consistent and add spaces around - too?
> +#define PKMAP_BASE (PKMAP_END - PAGE_SIZE * LAST_PKMAP)
>
> #ifdef CONFIG_HIGHMEM
> # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
MBR, Sergei
^ permalink raw reply [flat|nested] 9+ messages in thread