linux-parisc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] parisc: fix map_pages() to actually populate upper directory
@ 2020-01-08 12:58 Mike Rapoport
  2020-01-09  6:50 ` Helge Deller
  0 siblings, 1 reply; 4+ messages in thread
From: Mike Rapoport @ 2020-01-08 12:58 UTC (permalink / raw)
  To: James E.J. Bottomley
  Cc: Helge Deller, linux-parisc, linux-kernel, Mike Rapoport,
	Mike Rapoport, Meelis Roos, Jeroen Roovers, Mikulas Patocka

From: Mike Rapoport <rppt@linux.ibm.com>

The commit d96885e277b5 ("parisc: use pgtable-nopXd instead of
4level-fixup") converted PA-RISC to use folded page tables, but it missed
the conversion of pgd_populate() to pud_populate() in maps_pages()
function. This caused the upper page table directory to remain empty and
the system would crash as a result.

Using pud_populate() that actually populates the page table instead of
dummy pgd_populate() fixes the issue.

Fixes: d96885e277b5 ("parisc: use pgtable-nopXd instead of 4level-fixup")
Reported-by: Meelis Roos <mroos@linux.ee>
Reported-by: Jeroen Roovers <jer@gentoo.org>
Reported-by: Mikulas Patocka <mpatocka@redhat.com>
Tested-by: Jeroen Roovers <jer@gentoo.org>
Tested-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
---
 arch/parisc/mm/init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index ddca8287d43b..354cf060b67f 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -401,7 +401,7 @@ static void __init map_pages(unsigned long start_vaddr,
 			pmd = (pmd_t *) __pa(pmd);
 		}
 
-		pgd_populate(NULL, pg_dir, __va(pmd));
+		pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
 #endif
 		pg_dir++;
 
-- 
2.24.0


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

* Re: [PATCH] parisc: fix map_pages() to actually populate upper directory
  2020-01-08 12:58 [PATCH] parisc: fix map_pages() to actually populate upper directory Mike Rapoport
@ 2020-01-09  6:50 ` Helge Deller
  2020-01-09  8:45   ` Mike Rapoport
  0 siblings, 1 reply; 4+ messages in thread
From: Helge Deller @ 2020-01-09  6:50 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: James E.J. Bottomley, Helge Deller, linux-parisc, linux-kernel,
	Mike Rapoport, Meelis Roos, Jeroen Roovers, Mikulas Patocka

> The commit d96885e277b5 ("parisc: use pgtable-nopXd instead of
> 4level-fixup") converted PA-RISC to use folded page tables, but it missed
> the conversion of pgd_populate() to pud_populate() in maps_pages()
> function. This caused the upper page table directory to remain empty and
> the system would crash as a result.
>
> Using pud_populate() that actually populates the page table instead of
> dummy pgd_populate() fixes the issue.
> ...
> diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
> index ddca8287d43b..354cf060b67f 100644
> --- a/arch/parisc/mm/init.c
> +++ b/arch/parisc/mm/init.c
> @@ -401,7 +401,7 @@ static void __init map_pages(unsigned long start_vaddr,
>  			pmd = (pmd_t *) __pa(pmd);
>  		}
>
> -		pgd_populate(NULL, pg_dir, __va(pmd));
> +		pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
>  #endif

Wouldn't the untested patch below be more clean?

Helge

diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index ddca8287d43b..73de58f31f5f 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -387,6 +387,8 @@ static void __init map_pages(unsigned long start_vaddr,
 #if PTRS_PER_PMD == 1
 		pmd = (pmd_t *)__pa(pg_dir);
 #else
+		p4d_t *p4d;
+		pud_t *pud;
 		pmd = (pmd_t *)pgd_address(*pg_dir);

 		/*
@@ -401,7 +403,9 @@ static void __init map_pages(unsigned long start_vaddr,
 			pmd = (pmd_t *) __pa(pmd);
 		}

-		pgd_populate(NULL, pg_dir, __va(pmd));
+		p4d = p4d_offset(pg_dir, vaddr);
+		pud = pud_offset(p4d, vaddr);
+		pud_populate(NULL, pud, __va(pmd));
 #endif
 		pg_dir++;


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

* Re: [PATCH] parisc: fix map_pages() to actually populate upper directory
  2020-01-09  6:50 ` Helge Deller
@ 2020-01-09  8:45   ` Mike Rapoport
  2020-01-11 15:53     ` Helge Deller
  0 siblings, 1 reply; 4+ messages in thread
From: Mike Rapoport @ 2020-01-09  8:45 UTC (permalink / raw)
  To: Helge Deller
  Cc: Mike Rapoport, James E.J. Bottomley, linux-parisc, linux-kernel,
	Meelis Roos, Jeroen Roovers, Mikulas Patocka

Hi,

On Thu, Jan 09, 2020 at 07:50:55AM +0100, Helge Deller wrote:
> > The commit d96885e277b5 ("parisc: use pgtable-nopXd instead of
> > 4level-fixup") converted PA-RISC to use folded page tables, but it missed
> > the conversion of pgd_populate() to pud_populate() in maps_pages()
> > function. This caused the upper page table directory to remain empty and
> > the system would crash as a result.
> >
> > Using pud_populate() that actually populates the page table instead of
> > dummy pgd_populate() fixes the issue.
> > ...
> > diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
> > index ddca8287d43b..354cf060b67f 100644
> > --- a/arch/parisc/mm/init.c
> > +++ b/arch/parisc/mm/init.c
> > @@ -401,7 +401,7 @@ static void __init map_pages(unsigned long start_vaddr,
> >  			pmd = (pmd_t *) __pa(pmd);
> >  		}
> >
> > -		pgd_populate(NULL, pg_dir, __va(pmd));
> > +		pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
> >  #endif
> 
> Wouldn't the untested patch below be more clean?
> 
> Helge
> 
> diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
> index ddca8287d43b..73de58f31f5f 100644
> --- a/arch/parisc/mm/init.c
> +++ b/arch/parisc/mm/init.c
> @@ -387,6 +387,8 @@ static void __init map_pages(unsigned long start_vaddr,
>  #if PTRS_PER_PMD == 1
>  		pmd = (pmd_t *)__pa(pg_dir);
>  #else
> +		p4d_t *p4d;
> +		pud_t *pud;
>  		pmd = (pmd_t *)pgd_address(*pg_dir);
> 
>  		/*
> @@ -401,7 +403,9 @@ static void __init map_pages(unsigned long start_vaddr,
>  			pmd = (pmd_t *) __pa(pmd);
>  		}
> 
> -		pgd_populate(NULL, pg_dir, __va(pmd));
> +		p4d = p4d_offset(pg_dir, vaddr);
> +		pud = pud_offset(p4d, vaddr);
> +		pud_populate(NULL, pud, __va(pmd));
>  #endif
>  		pg_dir++;

I've tried to keep the changes to minimum :)
Otherwise I'd go with something even more surgical:

diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 354cf060b67f..94baa4382c29 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -351,7 +351,6 @@ static void __init map_pages(unsigned long start_vaddr,
 			     unsigned long start_paddr, unsigned long size,
 			     pgprot_t pgprot, int force)
 {
-	pgd_t *pg_dir;
 	pmd_t *pmd;
 	pte_t *pg_table;
 	unsigned long end_paddr;
@@ -372,8 +371,6 @@ static void __init map_pages(unsigned long start_vaddr,
 
 	end_paddr = start_paddr + size;
 
-	pg_dir = pgd_offset_k(start_vaddr);
-
 #if PTRS_PER_PMD == 1
 	start_pmd = 0;
 #else
@@ -384,50 +381,30 @@ static void __init map_pages(unsigned long start_vaddr,
 	address = start_paddr;
 	vaddr = start_vaddr;
 	while (address < end_paddr) {
-#if PTRS_PER_PMD == 1
-		pmd = (pmd_t *)__pa(pg_dir);
-#else
-		pmd = (pmd_t *)pgd_address(*pg_dir);
+		pgd_t *pgd = pgd_offset_k(vaddr);
+		p4d_t *p4d = p4d_offset(pgd, vaddr);
+		pud_t *pud = pud_offset(p4d, vaddr);
 
-		/*
-		 * pmd is physical at this point
-		 */
-
-		if (!pmd) {
+#if CONFIG_PGTABLE_LEVELS == 3
+		if (pud_none(*pud)) {
 			pmd = memblock_alloc(PAGE_SIZE << PMD_ORDER,
 					     PAGE_SIZE << PMD_ORDER);
 			if (!pmd)
 				panic("pmd allocation failed.\n");
-			pmd = (pmd_t *) __pa(pmd);
+			pud_populate(NULL, pud, pmd);
 		}
-
-		pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
 #endif
-		pg_dir++;
 
-		/* now change pmd to kernel virtual addresses */
-
-		pmd = (pmd_t *)__va(pmd) + start_pmd;
+		pmd = pmd_offset(pud, vaddr);
 		for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++, pmd++) {
-
-			/*
-			 * pg_table is physical at this point
-			 */
-
-			pg_table = (pte_t *)pmd_address(*pmd);
-			if (!pg_table) {
-				pg_table = memblock_alloc(PAGE_SIZE,
-							  PAGE_SIZE);
+			if (pmd_none(*pmd)) {
+				pg_table = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
 				if (!pg_table)
 					panic("page table allocation failed\n");
-				pg_table = (pte_t *) __pa(pg_table);
+				pmd_populate_kernel(NULL, pmd, pg_table);
 			}
 
-			pmd_populate_kernel(NULL, pmd, __va(pg_table));
-
-			/* now change pg_table to kernel virtual addresses */
-
-			pg_table = (pte_t *) __va(pg_table) + start_pte;
+			pg_table = pte_offset_kernel(pmd, vaddr);
 			for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++, pg_table++) {
 				pte_t pte;
 				pgprot_t prot;
 

-- 
Sincerely yours,
Mike.


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

* Re: [PATCH] parisc: fix map_pages() to actually populate upper directory
  2020-01-09  8:45   ` Mike Rapoport
@ 2020-01-11 15:53     ` Helge Deller
  0 siblings, 0 replies; 4+ messages in thread
From: Helge Deller @ 2020-01-11 15:53 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Mike Rapoport, James E.J. Bottomley, linux-parisc, linux-kernel,
	Meelis Roos, Jeroen Roovers, Mikulas Patocka

On 09.01.20 09:45, Mike Rapoport wrote:
> Hi,
>
> On Thu, Jan 09, 2020 at 07:50:55AM +0100, Helge Deller wrote:
>>> The commit d96885e277b5 ("parisc: use pgtable-nopXd instead of
>>> 4level-fixup") converted PA-RISC to use folded page tables, but it missed
>>> the conversion of pgd_populate() to pud_populate() in maps_pages()
>>> function. This caused the upper page table directory to remain empty and
>>> the system would crash as a result.
>>>
>>> Using pud_populate() that actually populates the page table instead of
>>> dummy pgd_populate() fixes the issue.
>>> ...
>>> diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
>>> index ddca8287d43b..354cf060b67f 100644
>>> --- a/arch/parisc/mm/init.c
>>> +++ b/arch/parisc/mm/init.c
>>> @@ -401,7 +401,7 @@ static void __init map_pages(unsigned long start_vaddr,
>>>  			pmd = (pmd_t *) __pa(pmd);
>>>  		}
>>>
>>> -		pgd_populate(NULL, pg_dir, __va(pmd));
>>> +		pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
>>>  #endif
>>
>> Wouldn't the untested patch below be more clean?
>>
>> Helge
>>
>> diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
>> index ddca8287d43b..73de58f31f5f 100644
>> --- a/arch/parisc/mm/init.c
>> +++ b/arch/parisc/mm/init.c
>> @@ -387,6 +387,8 @@ static void __init map_pages(unsigned long start_vaddr,
>>  #if PTRS_PER_PMD == 1
>>  		pmd = (pmd_t *)__pa(pg_dir);
>>  #else
>> +		p4d_t *p4d;
>> +		pud_t *pud;
>>  		pmd = (pmd_t *)pgd_address(*pg_dir);
>>
>>  		/*
>> @@ -401,7 +403,9 @@ static void __init map_pages(unsigned long start_vaddr,
>>  			pmd = (pmd_t *) __pa(pmd);
>>  		}
>>
>> -		pgd_populate(NULL, pg_dir, __va(pmd));
>> +		p4d = p4d_offset(pg_dir, vaddr);
>> +		pud = pud_offset(p4d, vaddr);
>> +		pud_populate(NULL, pud, __va(pmd));
>>  #endif
>>  		pg_dir++;
>
> I've tried to keep the changes to minimum :)
> Otherwise I'd go with something even more surgical:


Ok, then let's use the small fix for v5.5, and the bigger one for v5.6.
I'll push the small fixup to Linux through the parisc tree shortly.

Would you mind resending the full cleanup patch for v5.6 later again ?

Thanks!!
Helge

>
> diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
> index 354cf060b67f..94baa4382c29 100644
> --- a/arch/parisc/mm/init.c
> +++ b/arch/parisc/mm/init.c
> @@ -351,7 +351,6 @@ static void __init map_pages(unsigned long start_vaddr,
>  			     unsigned long start_paddr, unsigned long size,
>  			     pgprot_t pgprot, int force)
>  {
> -	pgd_t *pg_dir;
>  	pmd_t *pmd;
>  	pte_t *pg_table;
>  	unsigned long end_paddr;
> @@ -372,8 +371,6 @@ static void __init map_pages(unsigned long start_vaddr,
>
>  	end_paddr = start_paddr + size;
>
> -	pg_dir = pgd_offset_k(start_vaddr);
> -
>  #if PTRS_PER_PMD == 1
>  	start_pmd = 0;
>  #else
> @@ -384,50 +381,30 @@ static void __init map_pages(unsigned long start_vaddr,
>  	address = start_paddr;
>  	vaddr = start_vaddr;
>  	while (address < end_paddr) {
> -#if PTRS_PER_PMD == 1
> -		pmd = (pmd_t *)__pa(pg_dir);
> -#else
> -		pmd = (pmd_t *)pgd_address(*pg_dir);
> +		pgd_t *pgd = pgd_offset_k(vaddr);
> +		p4d_t *p4d = p4d_offset(pgd, vaddr);
> +		pud_t *pud = pud_offset(p4d, vaddr);
>
> -		/*
> -		 * pmd is physical at this point
> -		 */
> -
> -		if (!pmd) {
> +#if CONFIG_PGTABLE_LEVELS == 3
> +		if (pud_none(*pud)) {
>  			pmd = memblock_alloc(PAGE_SIZE << PMD_ORDER,
>  					     PAGE_SIZE << PMD_ORDER);
>  			if (!pmd)
>  				panic("pmd allocation failed.\n");
> -			pmd = (pmd_t *) __pa(pmd);
> +			pud_populate(NULL, pud, pmd);
>  		}
> -
> -		pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
>  #endif
> -		pg_dir++;
>
> -		/* now change pmd to kernel virtual addresses */
> -
> -		pmd = (pmd_t *)__va(pmd) + start_pmd;
> +		pmd = pmd_offset(pud, vaddr);
>  		for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++, pmd++) {
> -
> -			/*
> -			 * pg_table is physical at this point
> -			 */
> -
> -			pg_table = (pte_t *)pmd_address(*pmd);
> -			if (!pg_table) {
> -				pg_table = memblock_alloc(PAGE_SIZE,
> -							  PAGE_SIZE);
> +			if (pmd_none(*pmd)) {
> +				pg_table = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
>  				if (!pg_table)
>  					panic("page table allocation failed\n");
> -				pg_table = (pte_t *) __pa(pg_table);
> +				pmd_populate_kernel(NULL, pmd, pg_table);
>  			}
>
> -			pmd_populate_kernel(NULL, pmd, __va(pg_table));
> -
> -			/* now change pg_table to kernel virtual addresses */
> -
> -			pg_table = (pte_t *) __va(pg_table) + start_pte;
> +			pg_table = pte_offset_kernel(pmd, vaddr);
>  			for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++, pg_table++) {
>  				pte_t pte;
>  				pgprot_t prot;
>
>


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

end of thread, other threads:[~2020-01-11 15:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-08 12:58 [PATCH] parisc: fix map_pages() to actually populate upper directory Mike Rapoport
2020-01-09  6:50 ` Helge Deller
2020-01-09  8:45   ` Mike Rapoport
2020-01-11 15:53     ` Helge Deller

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