Skip to content

Commit

Permalink
powerpc/mm: Add a _PAGE_PTE bit
Browse files Browse the repository at this point in the history
For a pte entry we will have _PAGE_PTE set. Our pte page
address have a minimum alignment requirement of HUGEPD_SHIFT_MASK + 1.
We use the lower 7 bits to indicate hugepd. ie.

For pmd and pgd we can find:
1) _PAGE_PTE set pte -> indicate PTE
2) bits [2..6] non zero -> indicate hugepd.
   They also encode the size. We skip bit 1 (_PAGE_PRESENT).
3) othewise pointer to next table.

Acked-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
  • Loading branch information
Aneesh Kumar K.V authored and Michael Ellerman committed Dec 14, 2015
1 parent e34aa03 commit 6a119ea
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 33 deletions.
9 changes: 6 additions & 3 deletions arch/powerpc/include/asm/book3s/64/hash-4k.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,13 @@ static inline int pgd_huge(pgd_t pgd)
static inline int hugepd_ok(hugepd_t hpd)
{
/*
* hugepd pointer, bottom two bits == 00 and next 4 bits
* indicate size of table
* if it is not a pte and have hugepd shift mask
* set, then it is a hugepd directory pointer
*/
return (((hpd.pd & 0x3) == 0x0) && ((hpd.pd & HUGEPD_SHIFT_MASK) != 0));
if (!(hpd.pd & _PAGE_PTE) &&
((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
return true;
return false;
}
#define is_hugepd(hpd) (hugepd_ok(hpd))
#endif
Expand Down
23 changes: 9 additions & 14 deletions arch/powerpc/include/asm/book3s/64/hash-64k.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,25 +130,25 @@ extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
static inline int pmd_huge(pmd_t pmd)
{
/*
* leaf pte for huge page, bottom two bits != 00
* leaf pte for huge page
*/
return ((pmd_val(pmd) & 0x3) != 0x0);
return !!(pmd_val(pmd) & _PAGE_PTE);
}

static inline int pud_huge(pud_t pud)
{
/*
* leaf pte for huge page, bottom two bits != 00
* leaf pte for huge page
*/
return ((pud_val(pud) & 0x3) != 0x0);
return !!(pud_val(pud) & _PAGE_PTE);
}

static inline int pgd_huge(pgd_t pgd)
{
/*
* leaf pte for huge page, bottom two bits != 00
* leaf pte for huge page
*/
return ((pgd_val(pgd) & 0x3) != 0x0);
return !!(pgd_val(pgd) & _PAGE_PTE);
}
#define pgd_huge pgd_huge

Expand Down Expand Up @@ -236,10 +236,8 @@ static inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array,
*/
static inline int pmd_trans_huge(pmd_t pmd)
{
/*
* leaf pte for huge page, bottom two bits != 00
*/
return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE);
return !!((pmd_val(pmd) & (_PAGE_PTE | _PAGE_THP_HUGE)) ==
(_PAGE_PTE | _PAGE_THP_HUGE));
}

static inline int pmd_trans_splitting(pmd_t pmd)
Expand All @@ -251,10 +249,7 @@ static inline int pmd_trans_splitting(pmd_t pmd)

static inline int pmd_large(pmd_t pmd)
{
/*
* leaf pte for huge page, bottom two bits != 00
*/
return ((pmd_val(pmd) & 0x3) != 0x0);
return !!(pmd_val(pmd) & _PAGE_PTE);
}

static inline pmd_t pmd_mknotpresent(pmd_t pmd)
Expand Down
13 changes: 7 additions & 6 deletions arch/powerpc/include/asm/book3s/64/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
* We could create separate kernel read-only if we used the 3 PP bits
* combinations that newer processors provide but we currently don't.
*/
#define _PAGE_PRESENT 0x00001 /* software: pte contains a translation */
#define _PAGE_USER 0x00002 /* matches one of the PP bits */
#define _PAGE_PTE 0x00001
#define _PAGE_PRESENT 0x00002 /* software: pte contains a translation */
#define _PAGE_BIT_SWAP_TYPE 2
#define _PAGE_EXEC 0x00004 /* No execute on POWER4 and newer (we invert) */
#define _PAGE_GUARDED 0x00008
#define _PAGE_USER 0x00004 /* matches one of the PP bits */
#define _PAGE_EXEC 0x00008 /* No execute on POWER4 and newer (we invert) */
#define _PAGE_GUARDED 0x00010
/* We can derive Memory coherence from _PAGE_NO_CACHE */
#define _PAGE_COHERENT 0x0
#define _PAGE_NO_CACHE 0x00020 /* I: cache inhibit */
Expand Down Expand Up @@ -49,7 +50,7 @@
*/
#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | \
_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPLITTING | \
_PAGE_THP_HUGE)
_PAGE_THP_HUGE | _PAGE_PTE)

#ifdef CONFIG_PPC_64K_PAGES
#include <asm/book3s/64/hash-64k.h>
Expand Down Expand Up @@ -135,7 +136,7 @@
* pgprot changes
*/
#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
_PAGE_ACCESSED | _PAGE_SPECIAL)
_PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE)
/*
* Mask of bits returned by pte_pgprot()
*/
Expand Down
3 changes: 1 addition & 2 deletions arch/powerpc/include/asm/book3s/64/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ static inline int pmd_protnone(pmd_t pmd)

static inline pmd_t pmd_mkhuge(pmd_t pmd)
{
/* Do nothing, mk_pmd() does this part. */
return pmd;
return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_THP_HUGE));
}

#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/include/asm/pte-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
#else
#define _PAGE_RW 0
#endif

#ifndef _PAGE_PTE
#define _PAGE_PTE 0
#endif

#ifndef _PMD_PRESENT_MASK
#define _PMD_PRESENT_MASK _PMD_PRESENT
#endif
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,8 +894,8 @@ void flush_dcache_icache_hugepage(struct page *page)
* We have 4 cases for pgds and pmds:
* (1) invalid (all zeroes)
* (2) pointer to next table, as normal; bottom 6 bits == 0
* (3) leaf pte for huge page, bottom two bits != 00
* (4) hugepd pointer, bottom two bits == 00, next 4 bits indicate size of table
* (3) leaf pte for huge page _PAGE_PTE set
* (4) hugepd pointer, _PAGE_PTE = 0 and bits [2..6] indicate size of table
*
* So long as we atomically load page table pointers we are safe against teardown,
* we can follow the address down to the the page and take a ref on it.
Expand Down
4 changes: 4 additions & 0 deletions arch/powerpc/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
*/
VM_WARN_ON((pte_val(*ptep) & (_PAGE_PRESENT | _PAGE_USER)) ==
(_PAGE_PRESENT | _PAGE_USER));
/*
* Add the pte bit when tryint set a pte
*/
pte = __pte(pte_val(pte) | _PAGE_PTE);

/* Note: mm->context.id might not yet have been assigned as
* this context might not have been activated yet when this
Expand Down
7 changes: 1 addition & 6 deletions arch/powerpc/mm/pgtable_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,13 +765,8 @@ static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)
pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
{
unsigned long pmdv;
/*
* For a valid pte, we would have _PAGE_PRESENT always
* set. We use this to check THP page at pmd level.
* leaf pte for huge page, bottom two bits != 00
*/

pmdv = pfn << PTE_RPN_SHIFT;
pmdv |= _PAGE_THP_HUGE;
return pmd_set_protbits(__pmd(pmdv), pgprot);
}

Expand Down

0 comments on commit 6a119ea

Please sign in to comment.