diff mbox series

parisc: Add cacheflush() syscall

Message ID 20230601184105.678864-1-deller@gmx.de (mailing list archive)
State Accepted, archived
Headers show
Series parisc: Add cacheflush() syscall | expand

Commit Message

Helge Deller June 1, 2023, 6:41 p.m. UTC
Implement the missing cacheflush() syscall.

Signed-off-by: Helge Deller <deller@gmx.de>
---
 arch/parisc/include/asm/assembly.h      |  7 ++++
 arch/parisc/include/uapi/asm/cachectl.h | 12 +++++++
 arch/parisc/kernel/cache.c              | 46 +++++++++++++++++++++++++
 arch/parisc/kernel/syscalls/syscall.tbl |  1 +
 4 files changed, 66 insertions(+)
 create mode 100644 arch/parisc/include/uapi/asm/cachectl.h

--
2.40.1
diff mbox series

Patch

diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index 0f0d4a496fef..286fea9b6372 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -581,6 +581,13 @@ 
 	.word (fault_addr - .), (except_addr - .)	!	\
 	.previous

+#else /* __ASSEMBLY__ */
+
+#ifdef CONFIG_64BIT
+# define COND(x)	"*" __stringify(x)
+#else
+# define COND(x)	__stringify(x)
+#endif

 #endif /* __ASSEMBLY__ */
 #endif
diff --git a/arch/parisc/include/uapi/asm/cachectl.h b/arch/parisc/include/uapi/asm/cachectl.h
new file mode 100644
index 000000000000..68d6b455498b
--- /dev/null
+++ b/arch/parisc/include/uapi/asm/cachectl.h
@@ -0,0 +1,12 @@ 
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _ASM_CACHECTL
+#define _ASM_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ */
+#define ICACHE	(1<<0)		/* flush instruction cache	  */
+#define DCACHE	(1<<1)		/* writeback and flush data cache */
+#define BCACHE	(ICACHE|DCACHE) /* flush both caches		  */
+
+#endif	/* _ASM_CACHECTL */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index ca4a302d4365..b2c6da38a61c 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -19,6 +19,7 @@ 
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/sched/mm.h>
+#include <linux/syscalls.h>
 #include <asm/pdc.h>
 #include <asm/cache.h>
 #include <asm/cacheflush.h>
@@ -28,6 +29,7 @@ 
 #include <asm/sections.h>
 #include <asm/shmparam.h>
 #include <asm/mmu_context.h>
+#include <asm/cachectl.h>

 int split_tlb __ro_after_init;
 int dcache_stride __ro_after_init;
@@ -774,3 +776,47 @@  void invalidate_kernel_vmap_range(void *vaddr, int size)
 	flush_tlb_kernel_range(start, end);
 }
 EXPORT_SYMBOL(invalidate_kernel_vmap_range);
+
+SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
+	unsigned int, cache)
+{
+	unsigned long start, end;
+	ASM_EXCEPTIONTABLE_VAR(error);
+
+	if (bytes == 0)
+		return 0;
+	if (cache & ~BCACHE)
+		return -EINVAL;
+	if (!access_ok((void __user *) addr, bytes))
+		return -EFAULT;
+	if ((cache_info.dc_size == 0) && (cache_info.ic_size == 0))
+		return 0;
+
+	end = addr + bytes;
+	if (end < addr)
+		return -EINVAL;	/* wrap-around */
+
+	if (cache & ICACHE) {
+		start = addr;
+		__asm__ __volatile__ (
+			"1: cmpb," COND(<<) ",n	%0,%2,1b\n"
+			"   fic,m	%3(%4,%0)\n"
+			"2:\n"
+			ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b)
+			: "+r" (start), "+r" (error)
+			: "r" (end), "r" (icache_stride), "i" (SR_USER));
+	}
+
+	if (cache & DCACHE && error == 0) {
+		start = addr;
+		__asm__ __volatile__ (
+			"1: cmpb," COND(<<) ",n	%0,%2,1b\n"
+			"   fdc,m	%3(%4,%0)\n"
+			"2:\n"
+			ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b)
+			: "+r" (start), "+r" (error)
+			: "r" (end), "r" (dcache_stride), "i" (SR_USER));
+	}
+
+	return error;
+}
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index 0e42fceb2d5e..293c0484447b 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -400,6 +400,7 @@ 
 353	common	pkey_free		sys_pkey_free
 354	common	rseq			sys_rseq
 355	common	kexec_file_load		sys_kexec_file_load		sys_kexec_file_load
+356	common	cacheflush		sys_cacheflush
 # up to 402 is unassigned and reserved for arch specific syscalls
 403	32	clock_gettime64			sys_clock_gettime		sys_clock_gettime
 404	32	clock_settime64			sys_clock_settime		sys_clock_settime