summaryrefslogtreecommitdiffstats
path: root/include/asm-s390x/system.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390x/system.h')
-rw-r--r--include/asm-s390x/system.h264
1 files changed, 264 insertions, 0 deletions
diff --git a/include/asm-s390x/system.h b/include/asm-s390x/system.h
new file mode 100644
index 000000000..9d77dbc68
--- /dev/null
+++ b/include/asm-s390x/system.h
@@ -0,0 +1,264 @@
+/*
+ * include/asm-s390/system.h
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ * Derived from "include/asm-i386/system.h"
+ */
+
+#ifndef __ASM_SYSTEM_H
+#define __ASM_SYSTEM_H
+
+#include <linux/config.h>
+#ifdef __KERNEL__
+#include <asm/lowcore.h>
+#endif
+#include <linux/kernel.h>
+
+#define prepare_to_switch() do { } while(0)
+#define switch_to(prev,next,last) do { \
+ if (prev == next) \
+ break; \
+ save_fp_regs(&prev->thread.fp_regs); \
+ restore_fp_regs(&next->thread.fp_regs); \
+ last = resume(&prev->thread,&next->thread); \
+} while (0)
+
+struct task_struct;
+
+#define nop() __asm__ __volatile__ ("nop")
+
+#define xchg(ptr,x) \
+ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(void *)(ptr),sizeof(*(ptr))))
+
+
+static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+{
+ switch (size) {
+ case 1:
+ asm volatile (
+ " lghi 1,3\n"
+ " nr 1,%0\n" /* isolate last 2 bits */
+ " xr %0,1\n" /* align ptr */
+ " bras 2,0f\n"
+ " icm 1,8,%1\n" /* for ptr&3 == 0 */
+ " stcm 0,8,%1\n"
+ " icm 1,4,%1\n" /* for ptr&3 == 1 */
+ " stcm 0,4,%1\n"
+ " icm 1,2,%1\n" /* for ptr&3 == 2 */
+ " stcm 0,2,%1\n"
+ " icm 1,1,%1\n" /* for ptr&3 == 3 */
+ " stcm 0,1,%1\n"
+ "0: sll 1,3\n"
+ " la 2,0(1,2)\n" /* r2 points to an icm */
+ " l 0,0(%0)\n" /* get fullword */
+ "1: lr 1,0\n" /* cs loop */
+ " ex 0,0(2)\n" /* insert x */
+ " cs 0,1,0(%0)\n"
+ " jl 1b\n"
+ " ex 0,4(2)" /* store *ptr to x */
+ : "+&a" (ptr), "+m" (x) :
+ : "memory", "0", "1", "2");
+ case 2:
+ if(((addr_t)ptr)&1)
+ panic("misaligned (__u16 *) in __xchg\n");
+ asm volatile (
+ " lghi 1,2\n"
+ " nr 1,%0\n" /* isolate bit 2^1 */
+ " xr %0,1\n" /* align ptr */
+ " bras 2,0f\n"
+ " icm 1,12,%1\n" /* for ptr&2 == 0 */
+ " stcm 0,12,%1\n"
+ " icm 1,3,%1\n" /* for ptr&2 == 1 */
+ " stcm 0,3,%1\n"
+ "0: sll 1,2\n"
+ " la 2,0(1,2)\n" /* r2 points to an icm */
+ " l 0,0(%0)\n" /* get fullword */
+ "1: lr 1,0\n" /* cs loop */
+ " ex 0,0(2)\n" /* insert x */
+ " cs 0,1,0(%0)\n"
+ " jl 1b\n"
+ " ex 0,4(2)" /* store *ptr to x */
+ : "+&a" (ptr), "+m" (x) :
+ : "memory", "0", "1", "2");
+ break;
+ case 4:
+ if(((addr_t)ptr)&3)
+ panic("misaligned (__u32 *) in __xchg\n");
+ asm volatile (
+ " l 0,0(%1)\n"
+ "0: cs 0,%0,0(%1)\n"
+ " jl 0b\n"
+ " lgfr %0,0\n"
+ : "+d" (x) : "a" (ptr)
+ : "memory", "0" );
+ break;
+ case 8:
+ if(((addr_t)ptr)&7)
+ panic("misaligned (__u64 *) in __xchg\n");
+ asm volatile (
+ " lg 0,0(%1)\n"
+ "0: csg 0,%0,0(%1)\n"
+ " jl 0b\n"
+ " lgr %0,0\n"
+ : "+d" (x) : "a" (ptr)
+ : "memory", "0" );
+ break;
+ default:
+ abort();
+ }
+ return x;
+}
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * This is very similar to the ppc eieio/sync instruction in that is
+ * does a checkpoint syncronisation & makes sure that
+ * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ).
+ */
+
+#define eieio() __asm__ __volatile__ ("BCR 15,0")
+# define SYNC_OTHER_CORES(x) eieio()
+#define mb() eieio()
+#define rmb() eieio()
+#define wmb() eieio()
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#define smp_mb__before_clear_bit() smp_mb()
+#define smp_mb__after_clear_bit() smp_mb()
+
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+/* interrupt control.. */
+#define __sti() ({ \
+ unsigned long dummy; \
+ __asm__ __volatile__ ( \
+ "stosm %0,0x03" : "=m" (dummy) : : "memory"); \
+ })
+
+#define __cli() ({ \
+ unsigned long flags; \
+ __asm__ __volatile__ ( \
+ "stnsm %0,0xFC" : "=m" (flags) : : "memory"); \
+ flags; \
+ })
+
+#define __save_flags(x) \
+ __asm__ __volatile__("stosm %0,0" : "=m" (x) : : "memory")
+
+#define __restore_flags(x) \
+ __asm__ __volatile__("ssm %0" : : "m" (x) : "memory")
+
+#define __load_psw(psw) \
+ __asm__ __volatile__("lpswe %0" : : "m" (psw));
+
+#define __ctl_load(array, low, high) ({ \
+ __asm__ __volatile__ ( \
+ " la 1,%0\n" \
+ " bras 2,0f\n" \
+ " lctlg 0,0,0(1)\n" \
+ "0: ex %1,0(2)" \
+ : : "m" (array), "a" (((low)<<4)+(high)) : "1", "2" ); \
+ })
+
+#define __ctl_store(array, low, high) ({ \
+ __asm__ __volatile__ ( \
+ " la 1,%0\n" \
+ " bras 2,0f\n" \
+ " stctg 0,0,0(1)\n" \
+ "0: ex %1,0(2)" \
+ : "=m" (array) : "a" (((low)<<4)+(high)): "1", "2" ); \
+ })
+
+#define __ctl_set_bit(cr, bit) ({ \
+ __u8 dummy[24]; \
+ __asm__ __volatile__ ( \
+ " la 1,%0\n" /* align to 8 byte */ \
+ " aghi 1,7\n" \
+ " nill 1,0xfff8\n" \
+ " bras 2,0f\n" /* skip indirect insns */ \
+ " stctg 0,0,0(1)\n" \
+ " lctlg 0,0,0(1)\n" \
+ "0: ex %1,0(2)\n" /* execute stctl */ \
+ " lg 0,0(1)\n" \
+ " ogr 0,%2\n" /* set the bit */ \
+ " stg 0,0(1)\n" \
+ "1: ex %1,6(2)" /* execute lctl */ \
+ : "=m" (dummy) : "a" (cr*17), "a" (1L<<(bit)) \
+ : "0", "1", "2"); \
+ })
+
+#define __ctl_clear_bit(cr, bit) ({ \
+ __u8 dummy[24]; \
+ __asm__ __volatile__ ( \
+ " la 1,%0\n" /* align to 8 byte */ \
+ " aghi 1,7\n" \
+ " nill 1,0xfff8\n" \
+ " bras 2,0f\n" /* skip indirect insns */ \
+ " stctg 0,0,0(1)\n" \
+ " lctlg 0,0,0(1)\n" \
+ "0: ex %1,0(2)\n" /* execute stctl */ \
+ " lg 0,0(1)\n" \
+ " ngr 0,%2\n" /* set the bit */ \
+ " stg 0,0(1)\n" \
+ "1: ex %1,6(2)" /* execute lctl */ \
+ : "=m" (dummy) : "a" (cr*17), "a" (~(1L<<(bit))) \
+ : "0", "1", "2"); \
+ })
+
+/* For spinlocks etc */
+#define local_irq_save(x) ((x) = __cli())
+#define local_irq_restore(x) __restore_flags(x)
+#define local_irq_disable() __cli()
+#define local_irq_enable() __sti()
+
+#ifdef CONFIG_SMP
+
+extern void __global_cli(void);
+extern void __global_sti(void);
+
+extern unsigned long __global_save_flags(void);
+extern void __global_restore_flags(unsigned long);
+#define cli() __global_cli()
+#define sti() __global_sti()
+#define save_flags(x) ((x)=__global_save_flags())
+#define restore_flags(x) __global_restore_flags(x)
+
+extern void smp_ctl_set_bit(int cr, int bit);
+extern void smp_ctl_clear_bit(int cr, int bit);
+#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
+
+#else
+
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define restore_flags(x) __restore_flags(x)
+
+#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
+
+
+#endif
+
+#ifdef __KERNEL__
+extern struct task_struct *resume(void *,void *);
+
+extern int save_fp_regs1(s390_fp_regs *fpregs);
+extern void save_fp_regs(s390_fp_regs *fpregs);
+extern int restore_fp_regs1(s390_fp_regs *fpregs);
+extern void restore_fp_regs(s390_fp_regs *fpregs);
+#endif
+
+#endif
+
+
+