^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * High memory support for Xtensa architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This file is subject to the terms and conditions of the GNU General
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Public License. See the file "COPYING" in the main directory of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * this archive for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2014 Cadence Design Systems Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/highmem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/tlbflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static pte_t *kmap_pte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #if DCACHE_WAY_SIZE > PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void __init kmap_waitqueues_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) init_waitqueue_head(pkmap_map_wait_arr + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static inline void kmap_waitqueues_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) void *kmap_atomic_high_prot(struct page *page, pgprot_t prot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) enum fixed_addresses idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned long vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) idx = kmap_idx(kmap_atomic_idx_push(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) DCACHE_ALIAS(page_to_phys(page)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #ifdef CONFIG_DEBUG_HIGHMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) BUG_ON(!pte_none(*(kmap_pte + idx)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) set_pte(kmap_pte + idx, mk_pte(page, prot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return (void *)vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) EXPORT_SYMBOL(kmap_atomic_high_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void kunmap_atomic_high(void *kvaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (kvaddr >= (void *)FIXADDR_START &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) kvaddr < (void *)FIXADDR_TOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int idx = kmap_idx(kmap_atomic_idx(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) DCACHE_ALIAS((unsigned long)kvaddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Force other mappings to Oops if they'll try to access this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * pte without first remap it. Keeping stale mappings around
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * is a bad idea also, in case the page changes cacheability
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * attributes or becomes a protected page in a hypervisor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pte_clear(&init_mm, kvaddr, kmap_pte + idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) local_flush_tlb_kernel_range((unsigned long)kvaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) (unsigned long)kvaddr + PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) kmap_atomic_idx_pop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) EXPORT_SYMBOL(kunmap_atomic_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void __init kmap_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long kmap_vstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Check if this memory layout is broken because PKMAP overlaps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * page table.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* cache the first kmap pte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) kmap_pte = virt_to_kpte(kmap_vstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) kmap_waitqueues_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }