Commit d2791341 authored by Huacai Chen's avatar Huacai Chen
Browse files

LoongArch: Use TLB for ioremap()



We can support more cache attributes (e.g., CC, SUC and WUC) and page
protection when we use TLB for ioremap(). The implementation is based
on GENERIC_IOREMAP.

The existing simple ioremap() implementation has better performance so
we keep it and introduce ARCH_IOREMAP to control the selection.

We move pagetable_init() earlier to make early ioremap() works, and we
modify the PCI ecam mapping because the TLB-based version of ioremap()
will actually take the size into account.

Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 235d074f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ config LOONGARCH
	select GENERIC_CPU_AUTOPROBE
	select GENERIC_ENTRY
	select GENERIC_GETTIMEOFDAY
	select GENERIC_IOREMAP if !ARCH_IOREMAP
	select GENERIC_IRQ_MULTI_HANDLER
	select GENERIC_IRQ_PROBE
	select GENERIC_IRQ_SHOW
@@ -168,6 +169,9 @@ config MACH_LOONGSON32
config MACH_LOONGSON64
	def_bool 64BIT

config FIX_EARLYCON_MEM
	def_bool y

config PAGE_SIZE_4KB
	bool

@@ -404,6 +408,13 @@ config FORCE_MAX_ZONEORDER
	  The page size is not necessarily 4KB.  Keep this in mind
	  when choosing a value for this option.

config ARCH_IOREMAP
	bool "Enable LoongArch DMW-based ioremap()"
	help
	  We use generic TLB-based ioremap() by default since it has page
	  protection support. However, you can enable LoongArch DMW-based
	  ioremap() for better performance.

config SECCOMP
	bool "Enable seccomp to safely compute untrusted bytecode"
	depends on PROC_FS
+15 −0
Original line number Diff line number Diff line
@@ -10,4 +10,19 @@

#define NR_FIX_BTMAPS 64

enum fixed_addresses {
	FIX_HOLE,
	FIX_EARLYCON_MEM_BASE,
	__end_of_fixed_addresses
};

#define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
#define FIXMAP_PAGE_IO	PAGE_KERNEL_SUC

extern void __set_fixmap(enum fixed_addresses idx,
			 phys_addr_t phys, pgprot_t flags);

#include <asm-generic/fixmap.h>

#endif
+18 −51
Original line number Diff line number Diff line
@@ -27,71 +27,38 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size);
#define early_memremap early_ioremap
#define early_memunmap early_iounmap

#ifdef CONFIG_ARCH_IOREMAP

static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
					 unsigned long prot_val)
{
	if (prot_val == _CACHE_CC)
	if (prot_val & _CACHE_CC)
		return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
	else
		return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset);
}

/*
 * ioremap -   map bus memory into CPU space
 * @offset:    bus address of the memory
 * @size:      size of the resource to map
 *
 * ioremap performs a platform specific sequence of operations to
 * make bus memory CPU accessible via the readb/readw/readl/writeb/
 * writew/writel functions and the other mmio helpers. The returned
 * address is not guaranteed to be usable directly as a virtual
 * address.
 */
#define ioremap(offset, size)		\
	ioremap_prot((offset), (size), _CACHE_SUC)
	ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_SUC))

#define iounmap(addr) 			((void)(addr))

#endif

/*
 * ioremap_wc - map bus memory into CPU space
 * On LoongArch, ioremap() has two variants, ioremap_wc() and ioremap_cache().
 * They map bus memory into CPU space, the mapped memory is marked uncachable
 * (_CACHE_SUC), uncachable but accelerated by write-combine (_CACHE_WUC) and
 * cachable (_CACHE_CC) respectively for CPU access.
 *
 * @offset:    bus address of the memory
 * @size:      size of the resource to map
 *
 * ioremap_wc performs a platform specific sequence of operations to
 * make bus memory CPU accessible via the readb/readw/readl/writeb/
 * writew/writel functions and the other mmio helpers. The returned
 * address is not guaranteed to be usable directly as a virtual
 * address.
 *
 * This version of ioremap ensures that the memory is marked uncachable
 * but accelerated by means of write-combining feature. It is specifically
 * useful for PCIe prefetchable windows, which may vastly improve a
 * communications performance. If it was determined on boot stage, what
 * CPU CCA doesn't support WUC, the method shall fall-back to the
 * _CACHE_SUC option (see cpu_probe() method).
 */
#define ioremap_wc(offset, size)	\
	ioremap_prot((offset), (size), _CACHE_WUC)
	ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))

/*
 * ioremap_cache -  map bus memory into CPU space
 * @offset:	    bus address of the memory
 * @size:	    size of the resource to map
 *
 * ioremap_cache performs a platform specific sequence of operations to
 * make bus memory CPU accessible via the readb/readw/readl/writeb/
 * writew/writel functions and the other mmio helpers. The returned
 * address is not guaranteed to be usable directly as a virtual
 * address.
 *
 * This version of ioremap ensures that the memory is marked cachable by
 * the CPU.  Also enables full write-combining.	 Useful for some
 * memory-like regions on I/O busses.
 */
#define ioremap_cache(offset, size)	\
	ioremap_prot((offset), (size), _CACHE_CC)

static inline void iounmap(const volatile void __iomem *addr)
{
}
	ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))

#define mmiowb() asm volatile ("dbar 0" ::: "memory")

+3 −0
Original line number Diff line number Diff line
@@ -83,8 +83,11 @@
				 _PAGE_GLOBAL | _PAGE_KERN |  _CACHE_SUC)
#define PAGE_KERNEL_WUC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
				 _PAGE_GLOBAL | _PAGE_KERN |  _CACHE_WUC)

#ifndef __ASSEMBLY__

#define _PAGE_IOREMAP		pgprot_val(PAGE_KERNEL_SUC)

#define pgprot_noncached pgprot_noncached

static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+1 −1
Original line number Diff line number Diff line
@@ -348,10 +348,10 @@ void __init setup_arch(char **cmdline_p)
	init_environ();
	efi_init();
	memblock_init();
	pagetable_init();
	parse_early_param();

	platform_init();
	pagetable_init();
	arch_mem_init(cmdline_p);

	resource_init();
Loading