summaryrefslogtreecommitdiff
path: root/arch/parisc/include/asm/special_insns.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/include/asm/special_insns.h')
-rw-r--r--arch/parisc/include/asm/special_insns.h80
1 files changed, 69 insertions, 11 deletions
diff --git a/arch/parisc/include/asm/special_insns.h b/arch/parisc/include/asm/special_insns.h
index e1509308899f..1013eeba31e5 100644
--- a/arch/parisc/include/asm/special_insns.h
+++ b/arch/parisc/include/asm/special_insns.h
@@ -1,11 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PARISC_SPECIAL_INSNS_H
#define __PARISC_SPECIAL_INSNS_H
+#define lpa(va) ({ \
+ unsigned long pa; \
+ __asm__ __volatile__( \
+ "copy %%r0,%0\n" \
+ "8:\tlpa %%r0(%1),%0\n" \
+ "9:\n" \
+ ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \
+ "or %%r0,%%r0,%%r0") \
+ : "=&r" (pa) \
+ : "r" (va) \
+ : "memory" \
+ ); \
+ pa; \
+})
+
+#define lpa_user(va) ({ \
+ unsigned long pa; \
+ __asm__ __volatile__( \
+ "copy %%r0,%0\n" \
+ "8:\tlpa %%r0(%%sr3,%1),%0\n" \
+ "9:\n" \
+ ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \
+ "or %%r0,%%r0,%%r0") \
+ : "=&r" (pa) \
+ : "r" (va) \
+ : "memory" \
+ ); \
+ pa; \
+})
+
+/**
+ * prober_user() - Probe user read access
+ * @sr: Space regster.
+ * @va: Virtual address.
+ *
+ * Return: Non-zero if address is accessible.
+ *
+ * Due to the way _PAGE_READ is handled in TLB entries, we need
+ * a special check to determine whether a user address is accessible.
+ * The ldb instruction does the initial access check. If it is
+ * successful, the probe instruction checks user access rights.
+ */
+#define prober_user(sr, va) ({ \
+ unsigned long read_allowed; \
+ __asm__ __volatile__( \
+ "copy %%r0,%0\n" \
+ "8:\tldb 0(%%sr%1,%2),%%r0\n" \
+ "\tproberi (%%sr%1,%2),%3,%0\n" \
+ "9:\n" \
+ ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \
+ "or %%r0,%%r0,%%r0") \
+ : "=&r" (read_allowed) \
+ : "i" (sr), "r" (va), "i" (PRIV_USER) \
+ : "memory" \
+ ); \
+ read_allowed; \
+})
+
+#define CR_EIEM 15 /* External Interrupt Enable Mask */
+#define CR_CR16 16 /* CR16 Interval Timer */
+#define CR_EIRR 23 /* External Interrupt Request Register */
+
#define mfctl(reg) ({ \
unsigned long cr; \
__asm__ __volatile__( \
- "mfctl " #reg ",%0" : \
- "=r" (cr) \
+ "mfctl %1,%0" : \
+ "=r" (cr) : "i" (reg) \
); \
cr; \
})
@@ -15,19 +78,14 @@
: /* no outputs */ \
: "r" (gr), "i" (cr) : "memory")
-/* these are here to de-mystefy the calling code, and to provide hooks */
-/* which I needed for debugging EIEM problems -PB */
-#define get_eiem() mfctl(15)
-static inline void set_eiem(unsigned long val)
-{
- mtctl(val, 15);
-}
+#define get_eiem() mfctl(CR_EIEM)
+#define set_eiem(val) mtctl(val, CR_EIEM)
#define mfsp(reg) ({ \
unsigned long cr; \
__asm__ __volatile__( \
- "mfsp " #reg ",%0" : \
- "=r" (cr) \
+ "mfsp %%sr%1,%0" \
+ : "=r" (cr) : "i"(reg) \
); \
cr; \
})