diff options
Diffstat (limited to 'arch/sparc/mm/init_64.c')
-rw-r--r-- | arch/sparc/mm/init_64.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 809eecf6c797..12ef4ea60c88 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -2467,3 +2467,104 @@ void __flush_tlb_all(void) | |||
2467 | __asm__ __volatile__("wrpr %0, 0, %%pstate" | 2467 | __asm__ __volatile__("wrpr %0, 0, %%pstate" |
2468 | : : "r" (pstate)); | 2468 | : : "r" (pstate)); |
2469 | } | 2469 | } |
2470 | |||
2471 | static pte_t *get_from_cache(struct mm_struct *mm) | ||
2472 | { | ||
2473 | struct page *page; | ||
2474 | pte_t *ret; | ||
2475 | |||
2476 | spin_lock(&mm->page_table_lock); | ||
2477 | page = mm->context.pgtable_page; | ||
2478 | ret = NULL; | ||
2479 | if (page) { | ||
2480 | void *p = page_address(page); | ||
2481 | |||
2482 | mm->context.pgtable_page = NULL; | ||
2483 | |||
2484 | ret = (pte_t *) (p + (PAGE_SIZE / 2)); | ||
2485 | } | ||
2486 | spin_unlock(&mm->page_table_lock); | ||
2487 | |||
2488 | return ret; | ||
2489 | } | ||
2490 | |||
2491 | static struct page *__alloc_for_cache(struct mm_struct *mm) | ||
2492 | { | ||
2493 | struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | | ||
2494 | __GFP_REPEAT | __GFP_ZERO); | ||
2495 | |||
2496 | if (page) { | ||
2497 | spin_lock(&mm->page_table_lock); | ||
2498 | if (!mm->context.pgtable_page) { | ||
2499 | atomic_set(&page->_count, 2); | ||
2500 | mm->context.pgtable_page = page; | ||
2501 | } | ||
2502 | spin_unlock(&mm->page_table_lock); | ||
2503 | } | ||
2504 | return page; | ||
2505 | } | ||
2506 | |||
2507 | pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | ||
2508 | unsigned long address) | ||
2509 | { | ||
2510 | struct page *page; | ||
2511 | pte_t *pte; | ||
2512 | |||
2513 | pte = get_from_cache(mm); | ||
2514 | if (pte) | ||
2515 | return pte; | ||
2516 | |||
2517 | page = __alloc_for_cache(mm); | ||
2518 | if (page) | ||
2519 | pte = (pte_t *) page_address(page); | ||
2520 | |||
2521 | return pte; | ||
2522 | } | ||
2523 | |||
2524 | pgtable_t pte_alloc_one(struct mm_struct *mm, | ||
2525 | unsigned long address) | ||
2526 | { | ||
2527 | struct page *page; | ||
2528 | pte_t *pte; | ||
2529 | |||
2530 | pte = get_from_cache(mm); | ||
2531 | if (pte) | ||
2532 | return pte; | ||
2533 | |||
2534 | page = __alloc_for_cache(mm); | ||
2535 | if (page) { | ||
2536 | pgtable_page_ctor(page); | ||
2537 | pte = (pte_t *) page_address(page); | ||
2538 | } | ||
2539 | |||
2540 | return pte; | ||
2541 | } | ||
2542 | |||
2543 | void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
2544 | { | ||
2545 | struct page *page = virt_to_page(pte); | ||
2546 | if (put_page_testzero(page)) | ||
2547 | free_hot_cold_page(page, 0); | ||
2548 | } | ||
2549 | |||
2550 | static void __pte_free(pgtable_t pte) | ||
2551 | { | ||
2552 | struct page *page = virt_to_page(pte); | ||
2553 | if (put_page_testzero(page)) { | ||
2554 | pgtable_page_dtor(page); | ||
2555 | free_hot_cold_page(page, 0); | ||
2556 | } | ||
2557 | } | ||
2558 | |||
2559 | void pte_free(struct mm_struct *mm, pgtable_t pte) | ||
2560 | { | ||
2561 | __pte_free(pte); | ||
2562 | } | ||
2563 | |||
2564 | void pgtable_free(void *table, bool is_page) | ||
2565 | { | ||
2566 | if (is_page) | ||
2567 | __pte_free(table); | ||
2568 | else | ||
2569 | kmem_cache_free(pgtable_cache, table); | ||
2570 | } | ||