1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * arch/sh/mm/kmap.c |
4 | * |
5 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
6 | * Copyright (C) 2002 - 2009 Paul Mundt |
7 | */ |
8 | #include <linux/mm.h> |
9 | #include <linux/init.h> |
10 | #include <linux/mutex.h> |
11 | #include <linux/fs.h> |
12 | #include <linux/highmem.h> |
13 | #include <linux/module.h> |
14 | #include <asm/mmu_context.h> |
15 | #include <asm/cacheflush.h> |
16 | |
17 | static pte_t *kmap_coherent_pte; |
18 | |
19 | void __init kmap_coherent_init(void) |
20 | { |
21 | unsigned long vaddr; |
22 | |
23 | /* cache the first coherent kmap pte */ |
24 | vaddr = __fix_to_virt(FIX_CMAP_BEGIN); |
25 | kmap_coherent_pte = virt_to_kpte(vaddr); |
26 | } |
27 | |
28 | void *kmap_coherent(struct page *page, unsigned long addr) |
29 | { |
30 | struct folio *folio = page_folio(page); |
31 | enum fixed_addresses idx; |
32 | unsigned long vaddr; |
33 | |
34 | BUG_ON(!test_bit(PG_dcache_clean, &folio->flags)); |
35 | |
36 | preempt_disable(); |
37 | pagefault_disable(); |
38 | |
39 | idx = FIX_CMAP_END - |
40 | (((addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1)) + |
41 | (FIX_N_COLOURS * smp_processor_id())); |
42 | |
43 | vaddr = __fix_to_virt(idx); |
44 | |
45 | BUG_ON(!pte_none(*(kmap_coherent_pte - idx))); |
46 | set_pte(ptep: kmap_coherent_pte - idx, mk_pte(page, PAGE_KERNEL)); |
47 | |
48 | return (void *)vaddr; |
49 | } |
50 | |
51 | void kunmap_coherent(void *kvaddr) |
52 | { |
53 | if (kvaddr >= (void *)FIXADDR_START) { |
54 | unsigned long vaddr = (unsigned long)kvaddr & PAGE_MASK; |
55 | enum fixed_addresses idx = __virt_to_fix(vaddr); |
56 | |
57 | /* XXX.. Kill this later, here for sanity at the moment.. */ |
58 | __flush_purge_region((void *)vaddr, PAGE_SIZE); |
59 | |
60 | pte_clear(mm: &init_mm, addr: vaddr, ptep: kmap_coherent_pte - idx); |
61 | local_flush_tlb_one(get_asid(), vaddr); |
62 | } |
63 | |
64 | pagefault_enable(); |
65 | preempt_enable(); |
66 | } |
67 | |