Commit 06743521 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman

powerpc/mm: Add missing pmd accessors

This patch add documentation and missing accessors.
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 9e819963
...@@ -57,7 +57,21 @@ ...@@ -57,7 +57,21 @@
#define pgd_present(pgd) (pgd_val(pgd) != 0) #define pgd_present(pgd) (pgd_val(pgd) != 0)
#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0) #define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0)
#define pgd_page_vaddr(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS) #define pgd_page_vaddr(pgd) (pgd_val(pgd) & ~PGD_MASKED_BITS)
#define pgd_page(pgd) virt_to_page(pgd_page_vaddr(pgd))
#ifndef __ASSEMBLY__
static inline pte_t pgd_pte(pgd_t pgd)
{
return __pte(pgd_val(pgd));
}
static inline pgd_t pte_pgd(pte_t pte)
{
return __pgd(pte_val(pte));
}
extern struct page *pgd_page(pgd_t pgd);
#endif /* !__ASSEMBLY__ */
#define pud_offset(pgdp, addr) \ #define pud_offset(pgdp, addr) \
(((pud_t *) pgd_page_vaddr(*(pgdp))) + \ (((pud_t *) pgd_page_vaddr(*(pgdp))) + \
......
...@@ -38,4 +38,7 @@ ...@@ -38,4 +38,7 @@
/* Bits to mask out from a PGD/PUD to get to the PMD page */ /* Bits to mask out from a PGD/PUD to get to the PMD page */
#define PUD_MASKED_BITS 0x1ff #define PUD_MASKED_BITS 0x1ff
#define pgd_pte(pgd) (pud_pte(((pud_t){ pgd })))
#define pte_pgd(pte) ((pgd_t)pte_pud(pte))
#endif /* _ASM_POWERPC_PGTABLE_PPC64_64K_H */ #endif /* _ASM_POWERPC_PGTABLE_PPC64_64K_H */
...@@ -152,7 +152,7 @@ ...@@ -152,7 +152,7 @@
#define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (!is_kernel_addr(pmd_val(pmd)) \ #define pmd_bad(pmd) (!is_kernel_addr(pmd_val(pmd)) \
|| (pmd_val(pmd) & PMD_BAD_BITS)) || (pmd_val(pmd) & PMD_BAD_BITS))
#define pmd_present(pmd) (pmd_val(pmd) != 0) #define pmd_present(pmd) (!pmd_none(pmd))
#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0)
#define pmd_page_vaddr(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS) #define pmd_page_vaddr(pmd) (pmd_val(pmd) & ~PMD_MASKED_BITS)
extern struct page *pmd_page(pmd_t pmd); extern struct page *pmd_page(pmd_t pmd);
...@@ -164,9 +164,21 @@ extern struct page *pmd_page(pmd_t pmd); ...@@ -164,9 +164,21 @@ extern struct page *pmd_page(pmd_t pmd);
#define pud_present(pud) (pud_val(pud) != 0) #define pud_present(pud) (pud_val(pud) != 0)
#define pud_clear(pudp) (pud_val(*(pudp)) = 0) #define pud_clear(pudp) (pud_val(*(pudp)) = 0)
#define pud_page_vaddr(pud) (pud_val(pud) & ~PUD_MASKED_BITS) #define pud_page_vaddr(pud) (pud_val(pud) & ~PUD_MASKED_BITS)
#define pud_page(pud) virt_to_page(pud_page_vaddr(pud))
extern struct page *pud_page(pud_t pud);
static inline pte_t pud_pte(pud_t pud)
{
return __pte(pud_val(pud));
}
static inline pud_t pte_pud(pte_t pte)
{
return __pud(pte_val(pte));
}
#define pud_write(pud) pte_write(pud_pte(pud))
#define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);}) #define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
#define pgd_write(pgd) pte_write(pgd_pte(pgd))
/* /*
* Find an entry in a page-table-directory. We combine the address region * Find an entry in a page-table-directory. We combine the address region
...@@ -422,7 +434,22 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, ...@@ -422,7 +434,22 @@ extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd); pmd_t *pmdp, pmd_t pmd);
extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
pmd_t *pmd); pmd_t *pmd);
/*
*
* For core kernel code by design pmd_trans_huge is never run on any hugetlbfs
* page. The hugetlbfs page table walking and mangling paths are totally
* separated form the core VM paths and they're differentiated by
* VM_HUGETLB being set on vm_flags well before any pmd_trans_huge could run.
*
* pmd_trans_huge() is defined as false at build time if
* CONFIG_TRANSPARENT_HUGEPAGE=n to optimize away code blocks at build
* time in such case.
*
* For ppc64 we need to differntiate from explicit hugepages from THP, because
* for THP we also track the subpage details at the pmd level. We don't do
* that for explicit huge pages.
*
*/
static inline int pmd_trans_huge(pmd_t pmd) static inline int pmd_trans_huge(pmd_t pmd)
{ {
/* /*
...@@ -431,16 +458,6 @@ static inline int pmd_trans_huge(pmd_t pmd) ...@@ -431,16 +458,6 @@ static inline int pmd_trans_huge(pmd_t pmd)
return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE); return (pmd_val(pmd) & 0x3) && (pmd_val(pmd) & _PAGE_THP_HUGE);
} }
static inline int pmd_large(pmd_t pmd)
{
/*
* leaf pte for huge page, bottom two bits != 00
*/
if (pmd_trans_huge(pmd))
return pmd_val(pmd) & _PAGE_PRESENT;
return 0;
}
static inline int pmd_trans_splitting(pmd_t pmd) static inline int pmd_trans_splitting(pmd_t pmd)
{ {
if (pmd_trans_huge(pmd)) if (pmd_trans_huge(pmd))
...@@ -451,6 +468,14 @@ static inline int pmd_trans_splitting(pmd_t pmd) ...@@ -451,6 +468,14 @@ static inline int pmd_trans_splitting(pmd_t pmd)
extern int has_transparent_hugepage(void); extern int has_transparent_hugepage(void);
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
static inline int pmd_large(pmd_t pmd)
{
/*
* leaf pte for huge page, bottom two bits != 00
*/
return ((pmd_val(pmd) & 0x3) != 0x0);
}
static inline pte_t pmd_pte(pmd_t pmd) static inline pte_t pmd_pte(pmd_t pmd)
{ {
return __pte(pmd_val(pmd)); return __pte(pmd_val(pmd));
......
...@@ -62,6 +62,9 @@ static unsigned nr_gpages; ...@@ -62,6 +62,9 @@ static unsigned nr_gpages;
/* /*
* We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have
* 16GB hugepage pte in PGD and 16MB hugepage pte at PMD; * 16GB hugepage pte in PGD and 16MB hugepage pte at PMD;
*
* Defined in such a way that we can optimize away code block at build time
* if CONFIG_HUGETLB_PAGE=n.
*/ */
int pmd_huge(pmd_t pmd) int pmd_huge(pmd_t pmd)
{ {
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hugetlb.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -344,16 +345,31 @@ EXPORT_SYMBOL(iounmap); ...@@ -344,16 +345,31 @@ EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__iounmap); EXPORT_SYMBOL(__iounmap);
EXPORT_SYMBOL(__iounmap_at); EXPORT_SYMBOL(__iounmap_at);
#ifndef __PAGETABLE_PUD_FOLDED
/* 4 level page table */
struct page *pgd_page(pgd_t pgd)
{
if (pgd_huge(pgd))
return pte_page(pgd_pte(pgd));
return virt_to_page(pgd_page_vaddr(pgd));
}
#endif
struct page *pud_page(pud_t pud)
{
if (pud_huge(pud))
return pte_page(pud_pte(pud));
return virt_to_page(pud_page_vaddr(pud));
}
/* /*
* For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags * For hugepage we have pfn in the pmd, we use PTE_RPN_SHIFT bits for flags
* For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address. * For PTE page, we have a PTE_FRAG_SIZE (4K) aligned virtual address.
*/ */
struct page *pmd_page(pmd_t pmd) struct page *pmd_page(pmd_t pmd)
{ {
#ifdef CONFIG_TRANSPARENT_HUGEPAGE if (pmd_trans_huge(pmd) || pmd_huge(pmd))
if (pmd_trans_huge(pmd))
return pfn_to_page(pmd_pfn(pmd)); return pfn_to_page(pmd_pfn(pmd));
#endif
return virt_to_page(pmd_page_vaddr(pmd)); return virt_to_page(pmd_page_vaddr(pmd));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment