2014-12-08 14:16:49

by Christophe Leroy

[permalink] [raw]
Subject: [PATCH] powerpc32: missing accessors to pgprot_t objects

Compilation with #define STRICT_MM_TYPECHECKS in arch/powerpc/include/asm/page.h
fails due to missing use of pgprot_val() when using pgprot_t objects.

arch/powerpc/mm/pgtable_32.c: In function '__ioremap_caller':
arch/powerpc/mm/pgtable_32.c:185:9: error: invalid operands to binary | (have 'long unsigned int' and 'pgprot_t')
flags |= PAGE_KERNEL;
^
arch/powerpc/mm/pgtable_32.c: In function '__mapin_ram_chunk':
arch/powerpc/mm/pgtable_32.c:320:5: error: incompatible types when assigning to type 'long unsigned int' from type 'pgprot_t'
f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL;
^
arch/powerpc/mm/ppc_mmu_32.c:95:2: error: incompatible type for argument 5 of 'setbat'
setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X);
^
In file included from arch/powerpc/mm/ppc_mmu_32.c:35:0:
arch/powerpc/mm/mmu_decl.h:98:13: note: expected 'int' but argument is of type 'pgprot_t'
extern void setbat(int index, unsigned long virt, phys_addr_t phys,
^
arch/powerpc/mm/ppc_mmu_32.c:103:3: error: incompatible type for argument 5 of 'setbat'
setbat(3, PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
^
In file included from arch/powerpc/mm/ppc_mmu_32.c:35:0:
arch/powerpc/mm/mmu_decl.h:98:13: note: expected 'int' but argument is of type 'pgprot_t'
extern void setbat(int index, unsigned long virt, phys_addr_t phys,
^

Signed-off-by: Christophe Leroy <[email protected]>

---
arch/powerpc/mm/dma-noncoherent.c | 2 +-
arch/powerpc/mm/pgtable_32.c | 4 ++--
arch/powerpc/mm/ppc_mmu_32.c | 5 +++--
3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c
index d85e86a..169aba4 100644
--- a/arch/powerpc/mm/dma-noncoherent.c
+++ b/arch/powerpc/mm/dma-noncoherent.c
@@ -228,7 +228,7 @@ __dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t
do {
SetPageReserved(page);
map_page(vaddr, page_to_phys(page),
- pgprot_noncached(PAGE_KERNEL));
+ pgprot_val(pgprot_noncached(PAGE_KERNEL)));
page++;
vaddr += PAGE_SIZE;
} while (size -= PAGE_SIZE);
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index cf11342..a349089 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -182,7 +182,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,

/* Make sure we have the base flags */
if ((flags & _PAGE_PRESENT) == 0)
- flags |= PAGE_KERNEL;
+ flags |= pgprot_val(PAGE_KERNEL);

/* Non-cacheable page cannot be coherent */
if (flags & _PAGE_NO_CACHE)
@@ -317,7 +317,7 @@ void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
p = memstart_addr + s;
for (; s < top; s += PAGE_SIZE) {
ktext = ((char *) v >= _stext && (char *) v < etext);
- f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL;
+ f = pgprot_val(ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL);
map_page(v, p, f);
#ifdef CONFIG_PPC_STD_MMU_32
if (ktext)
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 5029dc1..dc710d4 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -92,7 +92,7 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
break;
}

- setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X);
+ setbat(2, PAGE_OFFSET, 0, bl, pgprot_val(PAGE_KERNEL_X));
done = (unsigned long)bat_addrs[2].limit - PAGE_OFFSET + 1;
if ((done < tot) && !bat_addrs[3].limit) {
/* use BAT3 to cover a bit more */
@@ -100,7 +100,8 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
for (bl = 128<<10; bl < max_size; bl <<= 1)
if (bl * 2 > tot)
break;
- setbat(3, PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
+ setbat(3, PAGE_OFFSET+done, done, bl,
+ pgprot_val(PAGE_KERNEL_X));
done = (unsigned long)bat_addrs[3].limit - PAGE_OFFSET + 1;
}

--
2.1.0


2014-12-09 10:06:20

by Michael Ellerman

[permalink] [raw]
Subject: Re: powerpc32: missing accessors to pgprot_t objects

On Mon, 2014-08-12 at 14:16:29 UTC, LEROY Christophe wrote:
> Compilation with #define STRICT_MM_TYPECHECKS in arch/powerpc/include/asm/page.h
> fails due to missing use of pgprot_val() when using pgprot_t objects.

Any idea when this broke? Recently, or has it gone unnoticed for a long time?

cheers

2014-12-09 10:14:04

by Benjamin Herrenschmidt

[permalink] [raw]
Subject: Re: powerpc32: missing accessors to pgprot_t objects

On Tue, 2014-12-09 at 21:06 +1100, Michael Ellerman wrote:
> On Mon, 2014-08-12 at 14:16:29 UTC, LEROY Christophe wrote:
> > Compilation with #define STRICT_MM_TYPECHECKS in arch/powerpc/include/asm/page.h
> > fails due to missing use of pgprot_val() when using pgprot_t objects.
>
> Any idea when this broke? Recently, or has it gone unnoticed for a long time?

Probably a very long time...

Now the reason we didn't leave STRICT_MM_TYPECHECKS enable back in the
day is that gcc was doing a terrible job at compiling it resulting in
bloated inefficient code.

I wouldn't be surprised if that is all fixed...

Cheers,
Ben.

2014-12-09 10:18:46

by Michael Ellerman

[permalink] [raw]
Subject: Re: powerpc32: missing accessors to pgprot_t objects

On Mon, 2014-08-12 at 14:16:29 UTC, LEROY Christophe wrote:
> Compilation with #define STRICT_MM_TYPECHECKS in arch/powerpc/include/asm/page.h
> fails due to missing use of pgprot_val() when using pgprot_t objects.

Hmm, looks like 64 bit doesn't build either.

Aneesh I think you added this, mind fixing it up?

In file included from ../arch/powerpc/include/asm/thread_info.h:34:0,
from ../include/linux/thread_info.h:54,
from ../include/asm-generic/preempt.h:4,
from arch/powerpc/include/generated/asm/preempt.h:1,
from ../include/linux/preempt.h:18,
from ../include/linux/spinlock.h:50,
from ../include/linux/mmzone.h:7,
from ../include/linux/gfp.h:5,
from ../include/linux/mm.h:9,
from ../arch/powerpc/mm/tlb_hash64.c:25:
../arch/powerpc/mm/tlb_hash64.c: In function ‘__flush_hash_table_range’:
../arch/powerpc/include/asm/page.h:286:24: error: request for member ‘pte’ in something not a structure or union
#define pte_val(x) ((x).pte)
^
../arch/powerpc/mm/tlb_hash64.c:219:37: note: in expansion of macro ‘pte_val’
trace_hugepage_invalidate(start, pte_val(pte));
^
make[2]: *** [arch/powerpc/mm/tlb_hash64.o] Error 1


cheers

2014-12-09 15:06:19

by Aneesh Kumar K.V

[permalink] [raw]
Subject: Re: powerpc32: missing accessors to pgprot_t objects

Michael Ellerman <[email protected]> writes:

> On Mon, 2014-08-12 at 14:16:29 UTC, LEROY Christophe wrote:
>> Compilation with #define STRICT_MM_TYPECHECKS in arch/powerpc/include/asm/page.h
>> fails due to missing use of pgprot_val() when using pgprot_t objects.
>
> Hmm, looks like 64 bit doesn't build either.
>
> Aneesh I think you added this, mind fixing it up?
>
> In file included from ../arch/powerpc/include/asm/thread_info.h:34:0,
> from ../include/linux/thread_info.h:54,
> from ../include/asm-generic/preempt.h:4,
> from arch/powerpc/include/generated/asm/preempt.h:1,
> from ../include/linux/preempt.h:18,
> from ../include/linux/spinlock.h:50,
> from ../include/linux/mmzone.h:7,
> from ../include/linux/gfp.h:5,
> from ../include/linux/mm.h:9,
> from ../arch/powerpc/mm/tlb_hash64.c:25:
> ../arch/powerpc/mm/tlb_hash64.c: In function ‘__flush_hash_table_range’:
> ../arch/powerpc/include/asm/page.h:286:24: error: request for member ‘pte’ in something not a structure or union
> #define pte_val(x) ((x).pte)
> ^
> ../arch/powerpc/mm/tlb_hash64.c:219:37: note: in expansion of macro ‘pte_val’
> trace_hugepage_invalidate(start, pte_val(pte));
> ^
> make[2]: *** [arch/powerpc/mm/tlb_hash64.o] Error 1
>

Will send a proper patch after compile testing with other configs. The
kvm hunk is really ugly, will try to rework.

diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 0aa8179..cd0ff37 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -291,11 +291,11 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing,
pte_t old_pte, new_pte = __pte(0);

while (1) {
- old_pte = pte_val(*ptep);
+ old_pte = *ptep;
/*
* wait until _PAGE_BUSY is clear then set it atomically
*/
- if (unlikely(old_pte & _PAGE_BUSY)) {
+ if (unlikely(pte_val(old_pte) & _PAGE_BUSY)) {
cpu_relax();
continue;
}
@@ -306,16 +306,18 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing,
return __pte(0);
#endif
/* If pte is not present return None */
- if (unlikely(!(old_pte & _PAGE_PRESENT)))
+ if (unlikely(!(pte_val(old_pte) & _PAGE_PRESENT)))
return __pte(0);

new_pte = pte_mkyoung(old_pte);
if (writing && pte_write(old_pte))
new_pte = pte_mkdirty(new_pte);

- if (old_pte == __cmpxchg_u64((unsigned long *)ptep, old_pte,
- new_pte))
+ if (pte_val(old_pte) == __cmpxchg_u64((unsigned long *)ptep,
+ pte_val(old_pte),
+ pte_val(new_pte))) {
break;
+ }
}
return new_pte;
}
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index 26fe1ae..cc62ab9 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -278,7 +278,7 @@ extern long long virt_phys_offset;

#ifndef __ASSEMBLY__

-#undef STRICT_MM_TYPECHECKS
+#define STRICT_MM_TYPECHECKS 1

#ifdef STRICT_MM_TYPECHECKS
/* These are used to make use of C type-checking. */
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 316f9a5..3e29088 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -77,8 +77,8 @@ static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
* which was inherited from x86. For the purposes of powerpc pte_basic_t and
* pmd_t are equivalent
*/
-#define pteval_t pte_basic_t
-#define pmdval_t pmd_t
+typedef unsigned long pteval_t;
+typedef unsigned long pmdval_t;
static inline pteval_t ptenuma_flags(pte_t pte)
{
return pte_val(pte) & _PAGE_NUMA_MASK;
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index c8d709a..5162936 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -714,7 +714,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
assert_spin_locked(&mm->page_table_lock);
WARN_ON(!pmd_trans_huge(pmd));
#endif
- trace_hugepage_set_pmd(addr, pmd);
+ trace_hugepage_set_pmd(addr, pmd_val(pmd));
return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
}

diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index d2a94b8..c522969 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -216,7 +216,7 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
continue;
pte = pte_val(*ptep);
if (hugepage_shift)
- trace_hugepage_invalidate(start, pte_val(pte));
+ trace_hugepage_invalidate(start, pte);
if (!(pte & _PAGE_HASHPTE))
continue;
if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte)))