Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Transparent Huge Pages support

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+243 -6
+12 -1
arch/mips/Kconfig
··· 19 19 select HAVE_KRETPROBES 20 20 select HAVE_DEBUG_KMEMLEAK 21 21 select ARCH_BINFMT_ELF_RANDOMIZE_PIE 22 + select HAVE_ARCH_TRANSPARENT_HUGEPAGE 22 23 select RTC_LIB if !MACH_LOONGSON 23 24 select GENERIC_ATOMIC64 if !64BIT 24 25 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE ··· 1373 1372 depends on SYS_HAS_CPU_R4X00 1374 1373 select CPU_SUPPORTS_32BIT_KERNEL 1375 1374 select CPU_SUPPORTS_64BIT_KERNEL 1375 + select CPU_SUPPORTS_HUGEPAGES 1376 1376 help 1377 1377 MIPS Technologies R4000-series processors other than 4300, including 1378 1378 the R4000, R4400, R4600, and 4700. ··· 1384 1382 select CPU_HAS_PREFETCH 1385 1383 select CPU_SUPPORTS_32BIT_KERNEL 1386 1384 select CPU_SUPPORTS_64BIT_KERNEL 1385 + select CPU_SUPPORTS_HUGEPAGES 1387 1386 1388 1387 config CPU_R5000 1389 1388 bool "R5000" 1390 1389 depends on SYS_HAS_CPU_R5000 1391 1390 select CPU_SUPPORTS_32BIT_KERNEL 1392 1391 select CPU_SUPPORTS_64BIT_KERNEL 1392 + select CPU_SUPPORTS_HUGEPAGES 1393 1393 help 1394 1394 MIPS Technologies R5000-series processors other than the Nevada. 1395 1395 ··· 1400 1396 depends on SYS_HAS_CPU_R5432 1401 1397 select CPU_SUPPORTS_32BIT_KERNEL 1402 1398 select CPU_SUPPORTS_64BIT_KERNEL 1399 + select CPU_SUPPORTS_HUGEPAGES 1403 1400 1404 1401 config CPU_R5500 1405 1402 bool "R5500" ··· 1426 1421 depends on SYS_HAS_CPU_NEVADA 1427 1422 select CPU_SUPPORTS_32BIT_KERNEL 1428 1423 select CPU_SUPPORTS_64BIT_KERNEL 1424 + select CPU_SUPPORTS_HUGEPAGES 1429 1425 help 1430 1426 QED / PMC-Sierra RM52xx-series ("Nevada") processors. 1431 1427 ··· 1447 1441 select CPU_SUPPORTS_32BIT_KERNEL 1448 1442 select CPU_SUPPORTS_64BIT_KERNEL 1449 1443 select CPU_SUPPORTS_HIGHMEM 1444 + select CPU_SUPPORTS_HUGEPAGES 1450 1445 help 1451 1446 MIPS Technologies R10000-series processors. 1452 1447 ··· 1458 1451 select CPU_SUPPORTS_32BIT_KERNEL 1459 1452 select CPU_SUPPORTS_64BIT_KERNEL 1460 1453 select CPU_SUPPORTS_HIGHMEM 1454 + select CPU_SUPPORTS_HUGEPAGES 1461 1455 1462 1456 config CPU_RM9000 1463 1457 bool "RM9000" ··· 1467 1459 select CPU_SUPPORTS_32BIT_KERNEL 1468 1460 select CPU_SUPPORTS_64BIT_KERNEL 1469 1461 select CPU_SUPPORTS_HIGHMEM 1462 + select CPU_SUPPORTS_HUGEPAGES 1470 1463 select WEAK_ORDERING 1471 1464 1472 1465 config CPU_SB1 ··· 1476 1467 select CPU_SUPPORTS_32BIT_KERNEL 1477 1468 select CPU_SUPPORTS_64BIT_KERNEL 1478 1469 select CPU_SUPPORTS_HIGHMEM 1470 + select CPU_SUPPORTS_HUGEPAGES 1479 1471 select WEAK_ORDERING 1480 1472 1481 1473 config CPU_CAVIUM_OCTEON ··· 1540 1530 select CPU_SUPPORTS_32BIT_KERNEL 1541 1531 select CPU_SUPPORTS_64BIT_KERNEL 1542 1532 select CPU_SUPPORTS_HIGHMEM 1533 + select CPU_SUPPORTS_HUGEPAGES 1543 1534 select WEAK_ORDERING 1544 1535 select WEAK_REORDERING_BEYOND_LLSC 1545 - select CPU_SUPPORTS_HUGEPAGES 1546 1536 help 1547 1537 Netlogic Microsystems XLR/XLS processors. 1548 1538 ··· 1603 1593 select CPU_SUPPORTS_32BIT_KERNEL 1604 1594 select CPU_SUPPORTS_64BIT_KERNEL 1605 1595 select CPU_SUPPORTS_HIGHMEM 1596 + select CPU_SUPPORTS_HUGEPAGES 1606 1597 1607 1598 config CPU_LOONGSON1 1608 1599 bool
+1 -1
arch/mips/include/asm/pgtable-64.h
··· 175 175 176 176 static inline int pmd_bad(pmd_t pmd) 177 177 { 178 - #ifdef CONFIG_HUGETLB_PAGE 178 + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT 179 179 /* pmd_huge(pmd) but inline */ 180 180 if (unlikely(pmd_val(pmd) & _PAGE_HUGE)) 181 181 return 0;
+10 -1
arch/mips/include/asm/pgtable-bits.h
··· 137 137 #define _PAGE_HUGE ({BUG(); 1; }) /* Dummy value */ 138 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 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 151 #define _PAGE_NO_EXEC ({BUG_ON(!cpu_has_rixi); 1 << _PAGE_NO_EXEC_SHIFT; }) 143 152 144 153 /* Page cannot be read */
+166 -1
arch/mips/include/asm/pgtable.h
··· 8 8 #ifndef _ASM_PGTABLE_H 9 9 #define _ASM_PGTABLE_H 10 10 11 + #include <linux/mmzone.h> 11 12 #ifdef CONFIG_32BIT 12 13 #include <asm/pgtable-32.h> 13 14 #endif ··· 95 94 * and a page entry and page directory to the page they refer to. 96 95 */ 97 96 #define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) 98 - #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) 97 + 98 + #define __pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) 99 + #ifndef CONFIG_TRANSPARENT_HUGEPAGE 100 + #define pmd_page(pmd) __pmd_page(pmd) 101 + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 102 + 99 103 #define pmd_page_vaddr(pmd) pmd_val(pmd) 100 104 101 105 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) ··· 380 374 __update_cache(vma, address, pte); 381 375 } 382 376 377 + static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, 378 + unsigned long address, pmd_t *pmdp) 379 + { 380 + pte_t pte = *(pte_t *)pmdp; 381 + 382 + __update_tlb(vma, address, pte); 383 + } 384 + 383 385 #define kern_addr_valid(addr) (1) 384 386 385 387 #ifdef CONFIG_64BIT_PHYS_ADDR ··· 406 392 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ 407 393 remap_pfn_range(vma, vaddr, pfn, size, prot) 408 394 #endif 395 + 396 + #ifdef CONFIG_TRANSPARENT_HUGEPAGE 397 + 398 + extern int has_transparent_hugepage(void); 399 + 400 + static inline int pmd_trans_huge(pmd_t pmd) 401 + { 402 + return !!(pmd_val(pmd) & _PAGE_HUGE); 403 + } 404 + 405 + static inline pmd_t pmd_mkhuge(pmd_t pmd) 406 + { 407 + pmd_val(pmd) |= _PAGE_HUGE; 408 + 409 + return pmd; 410 + } 411 + 412 + static inline int pmd_trans_splitting(pmd_t pmd) 413 + { 414 + return !!(pmd_val(pmd) & _PAGE_SPLITTING); 415 + } 416 + 417 + static inline pmd_t pmd_mksplitting(pmd_t pmd) 418 + { 419 + pmd_val(pmd) |= _PAGE_SPLITTING; 420 + 421 + return pmd; 422 + } 423 + 424 + extern void set_pmd_at(struct mm_struct *mm, unsigned long addr, 425 + pmd_t *pmdp, pmd_t pmd); 426 + 427 + #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH 428 + /* Extern to avoid header file madness */ 429 + extern void pmdp_splitting_flush(struct vm_area_struct *vma, 430 + unsigned long address, 431 + pmd_t *pmdp); 432 + 433 + #define __HAVE_ARCH_PMD_WRITE 434 + static inline int pmd_write(pmd_t pmd) 435 + { 436 + return !!(pmd_val(pmd) & _PAGE_WRITE); 437 + } 438 + 439 + static inline pmd_t pmd_wrprotect(pmd_t pmd) 440 + { 441 + pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); 442 + return pmd; 443 + } 444 + 445 + static inline pmd_t pmd_mkwrite(pmd_t pmd) 446 + { 447 + pmd_val(pmd) |= _PAGE_WRITE; 448 + if (pmd_val(pmd) & _PAGE_MODIFIED) 449 + pmd_val(pmd) |= _PAGE_SILENT_WRITE; 450 + 451 + return pmd; 452 + } 453 + 454 + static inline int pmd_dirty(pmd_t pmd) 455 + { 456 + return !!(pmd_val(pmd) & _PAGE_MODIFIED); 457 + } 458 + 459 + static inline pmd_t pmd_mkclean(pmd_t pmd) 460 + { 461 + pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); 462 + return pmd; 463 + } 464 + 465 + static inline pmd_t pmd_mkdirty(pmd_t pmd) 466 + { 467 + pmd_val(pmd) |= _PAGE_MODIFIED; 468 + if (pmd_val(pmd) & _PAGE_WRITE) 469 + pmd_val(pmd) |= _PAGE_SILENT_WRITE; 470 + 471 + return pmd; 472 + } 473 + 474 + static inline int pmd_young(pmd_t pmd) 475 + { 476 + return !!(pmd_val(pmd) & _PAGE_ACCESSED); 477 + } 478 + 479 + static inline pmd_t pmd_mkold(pmd_t pmd) 480 + { 481 + pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); 482 + 483 + return pmd; 484 + } 485 + 486 + static inline pmd_t pmd_mkyoung(pmd_t pmd) 487 + { 488 + pmd_val(pmd) |= _PAGE_ACCESSED; 489 + 490 + if (cpu_has_rixi) { 491 + if (!(pmd_val(pmd) & _PAGE_NO_READ)) 492 + pmd_val(pmd) |= _PAGE_SILENT_READ; 493 + } else { 494 + if (pmd_val(pmd) & _PAGE_READ) 495 + pmd_val(pmd) |= _PAGE_SILENT_READ; 496 + } 497 + 498 + return pmd; 499 + } 500 + 501 + /* Extern to avoid header file madness */ 502 + extern pmd_t mk_pmd(struct page *page, pgprot_t prot); 503 + 504 + static inline unsigned long pmd_pfn(pmd_t pmd) 505 + { 506 + return pmd_val(pmd) >> _PFN_SHIFT; 507 + } 508 + 509 + static inline struct page *pmd_page(pmd_t pmd) 510 + { 511 + if (pmd_trans_huge(pmd)) 512 + return pfn_to_page(pmd_pfn(pmd)); 513 + 514 + return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT); 515 + } 516 + 517 + static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 518 + { 519 + pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot); 520 + return pmd; 521 + } 522 + 523 + static inline pmd_t pmd_mknotpresent(pmd_t pmd) 524 + { 525 + pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY); 526 + 527 + return pmd; 528 + } 529 + 530 + /* 531 + * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a 532 + * different prototype. 533 + */ 534 + #define __HAVE_ARCH_PMDP_GET_AND_CLEAR 535 + static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, 536 + unsigned long address, pmd_t *pmdp) 537 + { 538 + pmd_t old = *pmdp; 539 + 540 + pmd_clear(pmdp); 541 + 542 + return old; 543 + } 544 + 545 + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 409 546 410 547 #include <asm-generic/pgtable.h> 411 548
+1 -1
arch/mips/kernel/mips_ksyms.c
··· 11 11 #include <linux/interrupt.h> 12 12 #include <linux/export.h> 13 13 #include <asm/checksum.h> 14 - #include <asm/pgtable.h> 14 + #include <linux/mm.h> 15 15 #include <asm/uaccess.h> 16 16 #include <asm/ftrace.h> 17 17
+31
arch/mips/mm/pgtable-64.c
··· 11 11 #include <asm/fixmap.h> 12 12 #include <asm/pgtable.h> 13 13 #include <asm/pgalloc.h> 14 + #include <asm/tlbflush.h> 14 15 15 16 void pgd_init(unsigned long page) 16 17 { ··· 61 60 } while (p != end); 62 61 } 63 62 #endif 63 + 64 + #ifdef CONFIG_TRANSPARENT_HUGEPAGE 65 + 66 + void pmdp_splitting_flush(struct vm_area_struct *vma, 67 + unsigned long address, 68 + pmd_t *pmdp) 69 + { 70 + if (!pmd_trans_splitting(*pmdp)) { 71 + pmd_t pmd = pmd_mksplitting(*pmdp); 72 + set_pmd_at(vma->vm_mm, address, pmdp, pmd); 73 + } 74 + } 75 + 76 + #endif 77 + 78 + pmd_t mk_pmd(struct page *page, pgprot_t prot) 79 + { 80 + pmd_t pmd; 81 + 82 + pmd_val(pmd) = (page_to_pfn(page) << _PFN_SHIFT) | pgprot_val(prot); 83 + 84 + return pmd; 85 + } 86 + 87 + void set_pmd_at(struct mm_struct *mm, unsigned long addr, 88 + pmd_t *pmdp, pmd_t pmd) 89 + { 90 + *pmdp = pmd; 91 + flush_tlb_all(); 92 + } 64 93 65 94 void __init pagetable_init(void) 66 95 {
+20
arch/mips/mm/tlb-r4k.c
··· 377 377 EXIT_CRITICAL(flags); 378 378 } 379 379 380 + #ifdef CONFIG_TRANSPARENT_HUGEPAGE 381 + 382 + int __init has_transparent_hugepage(void) 383 + { 384 + unsigned int mask; 385 + unsigned long flags; 386 + 387 + ENTER_CRITICAL(flags); 388 + write_c0_pagemask(PM_HUGE_MASK); 389 + back_to_back_c0_hazard(); 390 + mask = read_c0_pagemask(); 391 + write_c0_pagemask(PM_DEFAULT_MASK); 392 + 393 + EXIT_CRITICAL(flags); 394 + 395 + return mask == PM_HUGE_MASK; 396 + } 397 + 398 + #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 399 + 380 400 static int __cpuinitdata ntlb; 381 401 static int __init set_ntlb(char *str) 382 402 {
+2 -1
arch/mips/mm/tlbex.c
··· 225 225 pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT); 226 226 pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT); 227 227 pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT); 228 - #ifdef _PAGE_HUGE_SHIFT 228 + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT 229 229 pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT); 230 + pr_define("_PAGE_SPLITTING_SHIFT %d\n", _PAGE_SPLITTING_SHIFT); 230 231 #endif 231 232 if (cpu_has_rixi) { 232 233 #ifdef _PAGE_NO_EXEC_SHIFT