Commit 06fd881a authored by Huacai Chen's avatar Huacai Chen Committed by Hongchen Zhang
Browse files

LoongArch: Add writecombine support for DMW-based ioremap()

mainline inclusion
from mainline-v6.11-rc1
commit 8e02c3b782ec64343f3cccc8dc5a8be2b379e80b
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAZ33N
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8e02c3b782ec64343f3cccc8dc5a8be2b379e80b



----------------------------------------------------------------------

Currently, only TLB-based ioremap() support writecombine, so add the
counterpart for DMW-based ioremap() with help of DMW2. The base address
(WRITECOMBINE_BASE) is configured as 0xa000000000000000.

DMW3 is unused by kernel now, however firmware may leave garbage in them
and interfere kernel's address mapping. So clear it as necessary.

BTW, centralize the DMW configuration to macro SETUP_DMWINS.

Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 5e1e6937
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@ extern unsigned long vm_map_base;
#define UNCACHE_BASE		CSR_DMW0_BASE
#endif

#ifndef WRITECOMBINE_BASE
#define WRITECOMBINE_BASE	CSR_DMW2_BASE
#endif

#define DMW_PABITS	48
#define TO_PHYS_MASK	((1ULL << DMW_PABITS) - 1)

+8 −2
Original line number Diff line number Diff line
@@ -30,10 +30,16 @@ extern void __init early_iounmap(void __iomem *addr, unsigned long size);
static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
					 unsigned long prot_val)
{
	if (prot_val & _CACHE_CC)
	switch (prot_val & _CACHE_MASK) {
	case _CACHE_CC:
		return (void __iomem *)(unsigned long)(CACHE_BASE + offset);
	else
	case _CACHE_SUC:
		return (void __iomem *)(unsigned long)(UNCACHE_BASE + offset);
	case _CACHE_WUC:
		return (void __iomem *)(unsigned long)(WRITECOMBINE_BASE + offset);
	default:
		return NULL;
	}
}

#define ioremap(offset, size)		\
+9 −1
Original line number Diff line number Diff line
@@ -879,7 +879,7 @@
#define LOONGARCH_CSR_DMWIN2		0x182	/* 64 direct map win2: MEM */
#define LOONGARCH_CSR_DMWIN3		0x183	/* 64 direct map win3: MEM */

/* Direct Map window 0/1 */
/* Direct Map window 0/1/2/3 */
#define CSR_DMW0_PLV0		_CONST64_(1 << 0)
#define CSR_DMW0_VSEG		_CONST64_(0x8000)
#define CSR_DMW0_BASE		(CSR_DMW0_VSEG << DMW_PABITS)
@@ -891,6 +891,14 @@
#define CSR_DMW1_BASE		(CSR_DMW1_VSEG << DMW_PABITS)
#define CSR_DMW1_INIT		(CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW1_PLV0)

#define CSR_DMW2_PLV0		_CONST64_(1 << 0)
#define CSR_DMW2_MAT		_CONST64_(2 << 4)
#define CSR_DMW2_VSEG		_CONST64_(0xa000)
#define CSR_DMW2_BASE		(CSR_DMW2_VSEG << DMW_PABITS)
#define CSR_DMW2_INIT		(CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW2_PLV0)

#define CSR_DMW3_INIT		0x0

/* Performance Counter registers */
#define LOONGARCH_CSR_PERFCTRL0		0x200	/* 32 perf event 0 config */
#define LOONGARCH_CSR_PERFCNTR0		0x201	/* 64 perf event 0 count value */
+11 −0
Original line number Diff line number Diff line
@@ -37,6 +37,17 @@
	cfi_restore \reg \offset \docfi
	.endm

	.macro SETUP_DMWINS temp
	li.d	\temp, CSR_DMW0_INIT	# WUC, PLV0, 0x8000 xxxx xxxx xxxx
	csrwr	\temp, LOONGARCH_CSR_DMWIN0
	li.d	\temp, CSR_DMW1_INIT	# CAC, PLV0, 0x9000 xxxx xxxx xxxx
	csrwr	\temp, LOONGARCH_CSR_DMWIN1
	li.d	\temp, CSR_DMW2_INIT	# WUC, PLV0, 0xa000 xxxx xxxx xxxx
	csrwr	\temp, LOONGARCH_CSR_DMWIN2
	li.d	\temp, CSR_DMW3_INIT	# 0x0, unused
	csrwr	\temp, LOONGARCH_CSR_DMWIN3
	.endm

/* Jump to the runtime virtual address. */
	.macro JUMP_VIRT_ADDR temp1 temp2
	li.d	\temp1, CACHE_BASE
+2 −10
Original line number Diff line number Diff line
@@ -44,11 +44,7 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
SYM_CODE_START(kernel_entry)			# kernel entry point

	/* Config direct window and set PG */
	li.d		t0, CSR_DMW0_INIT	# UC, PLV0, 0x8000 xxxx xxxx xxxx
	csrwr		t0, LOONGARCH_CSR_DMWIN0
	li.d		t0, CSR_DMW1_INIT	# CA, PLV0, 0x9000 xxxx xxxx xxxx
	csrwr		t0, LOONGARCH_CSR_DMWIN1

	SETUP_DMWINS	t0
	JUMP_VIRT_ADDR	t0, t1

	/* Enable PG */
@@ -124,11 +120,7 @@ SYM_CODE_END(kernel_entry)
 * function after setting up the stack and tp registers.
 */
SYM_CODE_START(smpboot_entry)
	li.d		t0, CSR_DMW0_INIT	# UC, PLV0
	csrwr		t0, LOONGARCH_CSR_DMWIN0
	li.d		t0, CSR_DMW1_INIT	# CA, PLV0
	csrwr		t0, LOONGARCH_CSR_DMWIN1

	SETUP_DMWINS	t0
	JUMP_VIRT_ADDR	t0, t1

#ifdef CONFIG_PAGE_SIZE_4KB
Loading