diff options
| author | Ralf Baechle <ralf@linux-mips.org> | 2012-10-18 07:54:15 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2012-12-12 10:48:52 -0500 |
| commit | 970d032fec3f9687446595ee2569fb70b858a69f (patch) | |
| tree | 18fdf6999d82569a14a41021328f459a7f4bbd97 /arch/mips/include/asm | |
| parent | f65aad41772f6a0022e9763fe06f47604449964c (diff) | |
MIPS: Transparent Huge Pages support
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/include/asm')
| -rw-r--r-- | arch/mips/include/asm/pgtable-64.h | 2 | ||||
| -rw-r--r-- | arch/mips/include/asm/pgtable-bits.h | 11 | ||||
| -rw-r--r-- | arch/mips/include/asm/pgtable.h | 167 |
3 files changed, 177 insertions, 3 deletions
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index f5b521d5a67..c63191055e6 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h | |||
| @@ -175,7 +175,7 @@ static inline int pmd_none(pmd_t pmd) | |||
| 175 | 175 | ||
| 176 | static inline int pmd_bad(pmd_t pmd) | 176 | static inline int pmd_bad(pmd_t pmd) |
| 177 | { | 177 | { |
| 178 | #ifdef CONFIG_HUGETLB_PAGE | 178 | #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT |
| 179 | /* pmd_huge(pmd) but inline */ | 179 | /* pmd_huge(pmd) but inline */ |
| 180 | if (unlikely(pmd_val(pmd) & _PAGE_HUGE)) | 180 | if (unlikely(pmd_val(pmd) & _PAGE_HUGE)) |
| 181 | return 0; | 181 | return 0; |
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index 1e2642c360a..9ce1ac78244 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h | |||
| @@ -137,8 +137,17 @@ | |||
| 137 | #define _PAGE_HUGE ({BUG(); 1; }) /* Dummy value */ | 137 | #define _PAGE_HUGE ({BUG(); 1; }) /* Dummy value */ |
| 138 | #endif | 138 | #endif |
| 139 | 139 | ||
| 140 | #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT | ||
| 141 | /* huge tlb page */ | ||
| 142 | #define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT + 1) | ||
| 143 | #define _PAGE_SPLITTING (1 << _PAGE_SPLITTING_SHIFT) | ||
| 144 | #else | ||
| 145 | #define _PAGE_SPLITTING_SHIFT (_PAGE_HUGE_SHIFT) | ||
| 146 | #define _PAGE_SPLITTING ({BUG(); 1; }) /* Dummy value */ | ||
| 147 | #endif | ||
| 148 | |||
| 140 | /* Page cannot be executed */ | 149 | /* Page cannot be executed */ |
| 141 | #define _PAGE_NO_EXEC_SHIFT (cpu_has_rixi ? _PAGE_HUGE_SHIFT + 1 : _PAGE_HUGE_SHIFT) | 150 | #define _PAGE_NO_EXEC_SHIFT (cpu_has_rixi ? _PAGE_SPLITTING_SHIFT + 1 : _PAGE_SPLITTING_SHIFT) |
| 142 | #define _PAGE_NO_EXEC ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; }) | 151 | #define _PAGE_NO_EXEC ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; }) |
| 143 | 152 | ||
| 144 | /* Page cannot be read */ | 153 | /* Page cannot be read */ |
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index bc1c0fbf8d9..252202d24a8 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #ifndef _ASM_PGTABLE_H | 8 | #ifndef _ASM_PGTABLE_H |
| 9 | #define _ASM_PGTABLE_H | 9 | #define _ASM_PGTABLE_H |
| 10 | 10 | ||
| 11 | #include <linux/mmzone.h> | ||
| 11 | #ifdef CONFIG_32BIT | 12 | #ifdef CONFIG_32BIT |
| 12 | #include <asm/pgtable-32.h> | 13 | #include <asm/pgtable-32.h> |
| 13 | #endif | 14 | #endif |
| @@ -94,7 +95,12 @@ extern void paging_init(void); | |||
| 94 | * and a page entry and page directory to the page they refer to. | 95 | * and a page entry and page directory to the page they refer to. |
| 95 | */ | 96 | */ |
| 96 | #define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) | 97 | #define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) |
| 97 | #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) | 98 | |
| 99 | #define __pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) | ||
| 100 | #ifndef CONFIG_TRANSPARENT_HUGEPAGE | ||
| 101 | #define pmd_page(pmd) __pmd_page(pmd) | ||
| 102 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | ||
| 103 | |||
| 98 | #define pmd_page_vaddr(pmd) pmd_val(pmd) | 104 | #define pmd_page_vaddr(pmd) pmd_val(pmd) |
| 99 | 105 | ||
| 100 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 106 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) |
| @@ -374,6 +380,14 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, | |||
| 374 | __update_cache(vma, address, pte); | 380 | __update_cache(vma, address, pte); |
| 375 | } | 381 | } |
| 376 | 382 | ||
| 383 | static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, | ||
| 384 | unsigned long address, pmd_t *pmdp) | ||
| 385 | { | ||
| 386 | pte_t pte = *(pte_t *)pmdp; | ||
| 387 | |||
| 388 | __update_tlb(vma, address, pte); | ||
| 389 | } | ||
| 390 | |||
| 377 | #define kern_addr_valid(addr) (1) | 391 | #define kern_addr_valid(addr) (1) |
| 378 | 392 | ||
| 379 | #ifdef CONFIG_64BIT_PHYS_ADDR | 393 | #ifdef CONFIG_64BIT_PHYS_ADDR |
| @@ -393,6 +407,157 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma, | |||
| 393 | remap_pfn_range(vma, vaddr, pfn, size, prot) | 407 | remap_pfn_range(vma, vaddr, pfn, size, prot) |
| 394 | #endif | 408 | #endif |
| 395 | 409 | ||
| 410 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
| 411 | |||
| 412 | extern int has_transparent_hugepage(void); | ||
| 413 | |||
| 414 | static inline int pmd_trans_huge(pmd_t pmd) | ||
| 415 | { | ||
| 416 | return !!(pmd_val(pmd) & _PAGE_HUGE); | ||
| 417 | } | ||
| 418 | |||
| 419 | static inline pmd_t pmd_mkhuge(pmd_t pmd) | ||
| 420 | { | ||
| 421 | pmd_val(pmd) |= _PAGE_HUGE; | ||
| 422 | |||
| 423 | return pmd; | ||
| 424 | } | ||
| 425 | |||
| 426 | static inline int pmd_trans_splitting(pmd_t pmd) | ||
| 427 | { | ||
| 428 | return !!(pmd_val(pmd) & _PAGE_SPLITTING); | ||
| 429 | } | ||
| 430 | |||
| 431 | static inline pmd_t pmd_mksplitting(pmd_t pmd) | ||
| 432 | { | ||
| 433 | pmd_val(pmd) |= _PAGE_SPLITTING; | ||
| 434 | |||
| 435 | return pmd; | ||
| 436 | } | ||
| 437 | |||
| 438 | extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, | ||
| 439 | pmd_t *pmdp, pmd_t pmd); | ||
| 440 | |||
| 441 | #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH | ||
| 442 | /* Extern to avoid header file madness */ | ||
| 443 | extern void pmdp_splitting_flush(struct vm_area_struct *vma, | ||
| 444 | unsigned long address, | ||
| 445 | pmd_t *pmdp); | ||
| 446 | |||
| 447 | #define __HAVE_ARCH_PMD_WRITE | ||
| 448 | static inline int pmd_write(pmd_t pmd) | ||
| 449 | { | ||
| 450 | return !!(pmd_val(pmd) & _PAGE_WRITE); | ||
| 451 | } | ||
| 452 | |||
| 453 | static inline pmd_t pmd_wrprotect(pmd_t pmd) | ||
| 454 | { | ||
| 455 | pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); | ||
| 456 | return pmd; | ||
| 457 | } | ||
| 458 | |||
| 459 | static inline pmd_t pmd_mkwrite(pmd_t pmd) | ||
| 460 | { | ||
| 461 | pmd_val(pmd) |= _PAGE_WRITE; | ||
| 462 | if (pmd_val(pmd) & _PAGE_MODIFIED) | ||
| 463 | pmd_val(pmd) |= _PAGE_SILENT_WRITE; | ||
| 464 | |||
| 465 | return pmd; | ||
| 466 | } | ||
| 467 | |||
| 468 | static inline int pmd_dirty(pmd_t pmd) | ||
| 469 | { | ||
| 470 | return !!(pmd_val(pmd) & _PAGE_MODIFIED); | ||
| 471 | } | ||
| 472 | |||
| 473 | static inline pmd_t pmd_mkclean(pmd_t pmd) | ||
| 474 | { | ||
| 475 | pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); | ||
| 476 | return pmd; | ||
| 477 | } | ||
| 478 | |||
| 479 | static inline pmd_t pmd_mkdirty(pmd_t pmd) | ||
| 480 | { | ||
| 481 | pmd_val(pmd) |= _PAGE_MODIFIED; | ||
| 482 | if (pmd_val(pmd) & _PAGE_WRITE) | ||
| 483 | pmd_val(pmd) |= _PAGE_SILENT_WRITE; | ||
| 484 | |||
| 485 | return pmd; | ||
| 486 | } | ||
| 487 | |||
| 488 | static inline int pmd_young(pmd_t pmd) | ||
| 489 | { | ||
| 490 | return !!(pmd_val(pmd) & _PAGE_ACCESSED); | ||
| 491 | } | ||
| 492 | |||
| 493 | static inline pmd_t pmd_mkold(pmd_t pmd) | ||
| 494 | { | ||
| 495 | pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); | ||
| 496 | |||
| 497 | return pmd; | ||
| 498 | } | ||
| 499 | |||
| 500 | static inline pmd_t pmd_mkyoung(pmd_t pmd) | ||
| 501 | { | ||
| 502 | pmd_val(pmd) |= _PAGE_ACCESSED; | ||
| 503 | |||
| 504 | if (cpu_has_rixi) { | ||
| 505 | if (!(pmd_val(pmd) & _PAGE_NO_READ)) | ||
| 506 | pmd_val(pmd) |= _PAGE_SILENT_READ; | ||
| 507 | } else { | ||
| 508 | if (pmd_val(pmd) & _PAGE_READ) | ||
| 509 | pmd_val(pmd) |= _PAGE_SILENT_READ; | ||
| 510 | } | ||
| 511 | |||
| 512 | return pmd; | ||
| 513 | } | ||
| 514 | |||
| 515 | /* Extern to avoid header file madness */ | ||
| 516 | extern pmd_t mk_pmd(struct page *page, pgprot_t prot); | ||
| 517 | |||
| 518 | static inline unsigned long pmd_pfn(pmd_t pmd) | ||
| 519 | { | ||
| 520 | return pmd_val(pmd) >> _PFN_SHIFT; | ||
| 521 | } | ||
| 522 | |||
| 523 | static inline struct page *pmd_page(pmd_t pmd) | ||
| 524 | { | ||
| 525 | if (pmd_trans_huge(pmd)) | ||
| 526 | return pfn_to_page(pmd_pfn(pmd)); | ||
| 527 | |||
| 528 | return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT); | ||
| 529 | } | ||
| 530 | |||
| 531 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
| 532 | { | ||
| 533 | pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot); | ||
| 534 | return pmd; | ||
| 535 | } | ||
| 536 | |||
| 537 | static inline pmd_t pmd_mknotpresent(pmd_t pmd) | ||
| 538 | { | ||
| 539 | pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY); | ||
| 540 | |||
| 541 | return pmd; | ||
| 542 | } | ||
| 543 | |||
| 544 | /* | ||
| 545 | * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a | ||
| 546 | * different prototype. | ||
| 547 | */ | ||
| 548 | #define __HAVE_ARCH_PMDP_GET_AND_CLEAR | ||
| 549 | static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, | ||
| 550 | unsigned long address, pmd_t *pmdp) | ||
| 551 | { | ||
| 552 | pmd_t old = *pmdp; | ||
| 553 | |||
| 554 | pmd_clear(pmdp); | ||
| 555 | |||
| 556 | return old; | ||
| 557 | } | ||
| 558 | |||
| 559 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | ||
| 560 | |||
| 396 | #include <asm-generic/pgtable.h> | 561 | #include <asm-generic/pgtable.h> |
| 397 | 562 | ||
| 398 | /* | 563 | /* |
