aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm/init_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/mm/init_64.c')
-rw-r--r--arch/sparc/mm/init_64.c101
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
2471static 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
2491static 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
2507pte_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
2524pgtable_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
2543void 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
2550static 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
2559void pte_free(struct mm_struct *mm, pgtable_t pte)
2560{
2561 __pte_free(pte);
2562}
2563
2564void 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}