mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-21 22:32:45 +00:00
Patch series "Remove duplicated kmap code", v3. The kmap infrastructure has been copied almost verbatim to every architecture. This series consolidates obvious duplicated code by defining core functions which call into the architectures only when needed. Some of the k[un]map_atomic() implementations have some similarities but the similarities were not sufficient to warrant further changes. In addition we remove a duplicate implementation of kmap() in DRM. This patch (of 15): Replace the use of BUG_ON(in_interrupt()) in the kmap() and kunmap() in favor of might_sleep(). Besides the benefits of might_sleep(), this normalizes the implementations such that they can be made generic in subsequent patches. Signed-off-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christian König <christian.koenig@amd.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com> Cc: Helge Deller <deller@gmx.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Chris Zankel <chris@zankel.net> Cc: Max Filippov <jcmvbkbc@gmail.com> Link: http://lkml.kernel.org/r/20200507150004.1423069-1-ira.weiny@intel.com Link: http://lkml.kernel.org/r/20200507150004.1423069-2-ira.weiny@intel.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
130 lines
2.8 KiB
C
130 lines
2.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/compiler.h>
|
|
#include <linux/init.h>
|
|
#include <linux/export.h>
|
|
#include <linux/highmem.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/smp.h>
|
|
#include <asm/fixmap.h>
|
|
#include <asm/tlbflush.h>
|
|
|
|
static pte_t *kmap_pte;
|
|
|
|
unsigned long highstart_pfn, highend_pfn;
|
|
|
|
void *kmap(struct page *page)
|
|
{
|
|
void *addr;
|
|
|
|
might_sleep();
|
|
if (!PageHighMem(page))
|
|
return page_address(page);
|
|
addr = kmap_high(page);
|
|
flush_tlb_one((unsigned long)addr);
|
|
|
|
return addr;
|
|
}
|
|
EXPORT_SYMBOL(kmap);
|
|
|
|
void kunmap(struct page *page)
|
|
{
|
|
might_sleep();
|
|
if (!PageHighMem(page))
|
|
return;
|
|
kunmap_high(page);
|
|
}
|
|
EXPORT_SYMBOL(kunmap);
|
|
|
|
/*
|
|
* kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
|
|
* no global lock is needed and because the kmap code must perform a global TLB
|
|
* invalidation when the kmap pool wraps.
|
|
*
|
|
* However when holding an atomic kmap is is not legal to sleep, so atomic
|
|
* kmaps are appropriate for short, tight code paths only.
|
|
*/
|
|
|
|
void *kmap_atomic(struct page *page)
|
|
{
|
|
unsigned long vaddr;
|
|
int idx, type;
|
|
|
|
preempt_disable();
|
|
pagefault_disable();
|
|
if (!PageHighMem(page))
|
|
return page_address(page);
|
|
|
|
type = kmap_atomic_idx_push();
|
|
idx = type + KM_TYPE_NR*smp_processor_id();
|
|
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
|
#ifdef CONFIG_DEBUG_HIGHMEM
|
|
BUG_ON(!pte_none(*(kmap_pte - idx)));
|
|
#endif
|
|
set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL));
|
|
local_flush_tlb_one((unsigned long)vaddr);
|
|
|
|
return (void*) vaddr;
|
|
}
|
|
EXPORT_SYMBOL(kmap_atomic);
|
|
|
|
void __kunmap_atomic(void *kvaddr)
|
|
{
|
|
unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
|
|
int type __maybe_unused;
|
|
|
|
if (vaddr < FIXADDR_START) { // FIXME
|
|
pagefault_enable();
|
|
preempt_enable();
|
|
return;
|
|
}
|
|
|
|
type = kmap_atomic_idx();
|
|
#ifdef CONFIG_DEBUG_HIGHMEM
|
|
{
|
|
int idx = type + KM_TYPE_NR * smp_processor_id();
|
|
|
|
BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
|
|
|
|
/*
|
|
* force other mappings to Oops if they'll try to access
|
|
* this pte without first remap it
|
|
*/
|
|
pte_clear(&init_mm, vaddr, kmap_pte-idx);
|
|
local_flush_tlb_one(vaddr);
|
|
}
|
|
#endif
|
|
kmap_atomic_idx_pop();
|
|
pagefault_enable();
|
|
preempt_enable();
|
|
}
|
|
EXPORT_SYMBOL(__kunmap_atomic);
|
|
|
|
/*
|
|
* This is the same as kmap_atomic() but can map memory that doesn't
|
|
* have a struct page associated with it.
|
|
*/
|
|
void *kmap_atomic_pfn(unsigned long pfn)
|
|
{
|
|
unsigned long vaddr;
|
|
int idx, type;
|
|
|
|
preempt_disable();
|
|
pagefault_disable();
|
|
|
|
type = kmap_atomic_idx_push();
|
|
idx = type + KM_TYPE_NR*smp_processor_id();
|
|
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
|
set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
|
|
flush_tlb_one(vaddr);
|
|
|
|
return (void*) vaddr;
|
|
}
|
|
|
|
void __init kmap_init(void)
|
|
{
|
|
unsigned long kmap_vstart;
|
|
|
|
/* cache the first kmap pte */
|
|
kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
|
|
kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
|
|
}
|