Merge branch 'parisc-4.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc update from Helge Deller: "This patchset adds Huge Page and HUGETLBFS support for parisc" Honestly, the hugepage support should have gone through in the merge window, and is not really an rc-time fix. But it only touches arch/parisc, and I cannot find it in myself to care. If one of the three parisc users notices a breakage, I will point at Helge and make rude farting noises. * 'parisc-4.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: parisc: Map kernel text and data on huge pages parisc: Add Huge Page and HUGETLBFS support parisc: Use long branch to do_syscall_trace_exit parisc: Increase initial kernel mapping to 32MB on 64bit kernel parisc: Initialize the fault vector earlier in the boot process. parisc: Add defines for Huge page support parisc: Drop unused MADV_xxxK_PAGES flags from asm/mman.h parisc: Drop definition of start_thread_som for HP-UX SOM binaries parisc: Fix wrong comment regarding first pmd entry flags
This commit is contained in:
85
arch/parisc/include/asm/hugetlb.h
Normal file
85
arch/parisc/include/asm/hugetlb.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef _ASM_PARISC64_HUGETLB_H
|
||||
#define _ASM_PARISC64_HUGETLB_H
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm-generic/hugetlb.h>
|
||||
|
||||
|
||||
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte);
|
||||
|
||||
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep);
|
||||
|
||||
static inline int is_hugepage_only_range(struct mm_struct *mm,
|
||||
unsigned long addr,
|
||||
unsigned long len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the arch doesn't supply something else, assume that hugepage
|
||||
* size aligned regions are ok without further preparation.
|
||||
*/
|
||||
static inline int prepare_hugepage_range(struct file *file,
|
||||
unsigned long addr, unsigned long len)
|
||||
{
|
||||
if (len & ~HPAGE_MASK)
|
||||
return -EINVAL;
|
||||
if (addr & ~HPAGE_MASK)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
|
||||
unsigned long addr, unsigned long end,
|
||||
unsigned long floor,
|
||||
unsigned long ceiling)
|
||||
{
|
||||
free_pgd_range(tlb, addr, end, floor, ceiling);
|
||||
}
|
||||
|
||||
static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int huge_pte_none(pte_t pte)
|
||||
{
|
||||
return pte_none(pte);
|
||||
}
|
||||
|
||||
static inline pte_t huge_pte_wrprotect(pte_t pte)
|
||||
{
|
||||
return pte_wrprotect(pte);
|
||||
}
|
||||
|
||||
static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_t old_pte = *ptep;
|
||||
set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
|
||||
}
|
||||
|
||||
static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep,
|
||||
pte_t pte, int dirty)
|
||||
{
|
||||
int changed = !pte_same(*ptep, pte);
|
||||
if (changed) {
|
||||
set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
|
||||
flush_tlb_page(vma, addr);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
static inline pte_t huge_ptep_get(pte_t *ptep)
|
||||
{
|
||||
return *ptep;
|
||||
}
|
||||
|
||||
static inline void arch_clear_hugepage_flags(struct page *page)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* _ASM_PARISC64_HUGETLB_H */
|
@@ -145,11 +145,22 @@ extern int npmem_ranges;
|
||||
#endif /* CONFIG_DISCONTIGMEM */
|
||||
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
#define HPAGE_SHIFT 22 /* 4MB (is this fixed?) */
|
||||
#define HPAGE_SHIFT PMD_SHIFT /* fixed for transparent huge pages */
|
||||
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
|
||||
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
|
||||
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
|
||||
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
|
||||
# define REAL_HPAGE_SHIFT 20 /* 20 = 1MB */
|
||||
# define _HUGE_PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_1M
|
||||
#elif !defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB)
|
||||
# define REAL_HPAGE_SHIFT 22 /* 22 = 4MB */
|
||||
# define _HUGE_PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4M
|
||||
#else
|
||||
# define REAL_HPAGE_SHIFT 24 /* 24 = 16MB */
|
||||
# define _HUGE_PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_16M
|
||||
#endif
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
|
||||
|
||||
|
@@ -35,7 +35,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||
PxD_FLAG_VALID |
|
||||
PxD_FLAG_ATTACHED)
|
||||
+ (__u32)(__pa((unsigned long)pgd) >> PxD_VALUE_SHIFT));
|
||||
/* The first pmd entry also is marked with _PAGE_GATEWAY as
|
||||
/* The first pmd entry also is marked with PxD_FLAG_ATTACHED as
|
||||
* a signal that this pmd may not be freed */
|
||||
__pgd_val_set(*pgd, PxD_FLAG_ATTACHED);
|
||||
#endif
|
||||
|
@@ -83,7 +83,11 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
|
||||
printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e))
|
||||
|
||||
/* This is the size of the initially mapped kernel memory */
|
||||
#define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */
|
||||
#ifdef CONFIG_64BIT
|
||||
#define KERNEL_INITIAL_ORDER 25 /* 1<<25 = 32MB */
|
||||
#else
|
||||
#define KERNEL_INITIAL_ORDER 24 /* 1<<24 = 16MB */
|
||||
#endif
|
||||
#define KERNEL_INITIAL_SIZE (1 << KERNEL_INITIAL_ORDER)
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 3
|
||||
@@ -167,7 +171,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
|
||||
#define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */
|
||||
#define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */
|
||||
#define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */
|
||||
/* bit 21 was formerly the FLUSH bit but is now unused */
|
||||
#define _PAGE_HPAGE_BIT 21 /* (0x400) Software: Huge Page */
|
||||
#define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */
|
||||
|
||||
/* N.B. The bits are defined in terms of a 32 bit word above, so the */
|
||||
@@ -194,6 +198,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
|
||||
#define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT))
|
||||
#define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT))
|
||||
#define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT))
|
||||
#define _PAGE_HUGE (1 << xlate_pabit(_PAGE_HPAGE_BIT))
|
||||
#define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT))
|
||||
|
||||
#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED)
|
||||
@@ -217,7 +222,7 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
|
||||
#define PxD_FLAG_VALID (1 << xlate_pabit(_PxD_VALID_BIT))
|
||||
#define PxD_FLAG_MASK (0xf)
|
||||
#define PxD_FLAG_SHIFT (4)
|
||||
#define PxD_VALUE_SHIFT (8) /* (PAGE_SHIFT-PxD_FLAG_SHIFT) */
|
||||
#define PxD_VALUE_SHIFT (PFN_PTE_SHIFT-PxD_FLAG_SHIFT)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@@ -362,6 +367,18 @@ static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; ret
|
||||
static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; }
|
||||
static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
|
||||
|
||||
/*
|
||||
* Huge pte definitions.
|
||||
*/
|
||||
#ifdef CONFIG_HUGETLB_PAGE
|
||||
#define pte_huge(pte) (pte_val(pte) & _PAGE_HUGE)
|
||||
#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_HUGE))
|
||||
#else
|
||||
#define pte_huge(pte) (0)
|
||||
#define pte_mkhuge(pte) (pte)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Conversion functions: convert a page and protection to a page entry,
|
||||
* and a page entry and page directory to the page they refer to.
|
||||
@@ -410,8 +427,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
/* Find an entry in the second-level page table.. */
|
||||
|
||||
#if CONFIG_PGTABLE_LEVELS == 3
|
||||
#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
|
||||
#define pmd_offset(dir,address) \
|
||||
((pmd_t *) pgd_page_vaddr(*(dir)) + (((address)>>PMD_SHIFT) & (PTRS_PER_PMD-1)))
|
||||
((pmd_t *) pgd_page_vaddr(*(dir)) + pmd_index(address))
|
||||
#else
|
||||
#define pmd_offset(dir,addr) ((pmd_t *) dir)
|
||||
#endif
|
||||
|
@@ -192,33 +192,6 @@ void show_trace(struct task_struct *task, unsigned long *stack);
|
||||
*/
|
||||
typedef unsigned int elf_caddr_t;
|
||||
|
||||
#define start_thread_som(regs, new_pc, new_sp) do { \
|
||||
unsigned long *sp = (unsigned long *)new_sp; \
|
||||
__u32 spaceid = (__u32)current->mm->context; \
|
||||
unsigned long pc = (unsigned long)new_pc; \
|
||||
/* offset pc for priv. level */ \
|
||||
pc |= 3; \
|
||||
\
|
||||
regs->iasq[0] = spaceid; \
|
||||
regs->iasq[1] = spaceid; \
|
||||
regs->iaoq[0] = pc; \
|
||||
regs->iaoq[1] = pc + 4; \
|
||||
regs->sr[2] = LINUX_GATEWAY_SPACE; \
|
||||
regs->sr[3] = 0xffff; \
|
||||
regs->sr[4] = spaceid; \
|
||||
regs->sr[5] = spaceid; \
|
||||
regs->sr[6] = spaceid; \
|
||||
regs->sr[7] = spaceid; \
|
||||
regs->gr[ 0] = USER_PSW; \
|
||||
regs->gr[30] = ((new_sp)+63)&~63; \
|
||||
regs->gr[31] = pc; \
|
||||
\
|
||||
get_user(regs->gr[26],&sp[0]); \
|
||||
get_user(regs->gr[25],&sp[-1]); \
|
||||
get_user(regs->gr[24],&sp[-2]); \
|
||||
get_user(regs->gr[23],&sp[-3]); \
|
||||
} while(0)
|
||||
|
||||
/* The ELF abi wants things done a "wee bit" differently than
|
||||
* som does. Supporting this behavior here avoids
|
||||
* having our own version of create_elf_tables.
|
||||
|
Reference in New Issue
Block a user