Commit 9f0ff519 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390 update (15/27): 64 bit spinlocks.

Use diag 0x44 on s390x for spinlocks.
parent 33ccf4bd
...@@ -555,6 +555,17 @@ startup:basr %r13,0 # get base ...@@ -555,6 +555,17 @@ startup:basr %r13,0 # get base
oi 7(%r12),16 # set MVPG flag oi 7(%r12),16 # set MVPG flag
0: 0:
#
# find out if the diag 0x44 works in 64 bit mode
#
la %r1,0f-.LPG1(%r13) # set program check address
stg %r1,__LC_PGM_NEW_PSW+8
mvc __LC_DIAG44_OPCODE(8),.Lnop-.LPG1(%r13)
diag 0,0,0x44 # test diag 0x44
oi 7(%r12),32 # set diag44 flag
mvc __LC_DIAG44_OPCODE(8),.Ldiag44-.LPG1(%r13)
0:
lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
# virtual and never return ... # virtual and never return ...
.align 16 .align 16
...@@ -578,6 +589,8 @@ startup:basr %r13,0 # get base ...@@ -578,6 +589,8 @@ startup:basr %r13,0 # get base
.Lpcmsk:.quad 0x0000000180000000 .Lpcmsk:.quad 0x0000000180000000
.L4malign:.quad 0xffffffffffc00000 .L4malign:.quad 0xffffffffffc00000
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
.Lnop: .long 0x07000700
.Ldiag44:.long 0x83000044
.org PARMAREA-64 .org PARMAREA-64
.Lduct: .long 0,0,0,0,0,0,0,0 .Lduct: .long 0,0,0,0,0,0,0,0
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#define __LC_IO_INT_WORD 0x0C0 #define __LC_IO_INT_WORD 0x0C0
#define __LC_MCCK_CODE 0x0E8 #define __LC_MCCK_CODE 0x0E8
#define __LC_DIAG44_OPCODE 0x214
#define __LC_SAVE_AREA 0xC00 #define __LC_SAVE_AREA 0xC00
#define __LC_KERNEL_STACK 0xD40 #define __LC_KERNEL_STACK 0xD40
#define __LC_ASYNC_STACK 0xD48 #define __LC_ASYNC_STACK 0xD48
...@@ -146,7 +148,8 @@ struct _lowcore ...@@ -146,7 +148,8 @@ struct _lowcore
psw_t io_new_psw; /* 0x1f0 */ psw_t io_new_psw; /* 0x1f0 */
psw_t return_psw; /* 0x200 */ psw_t return_psw; /* 0x200 */
__u32 sync_io_word; /* 0x210 */ __u32 sync_io_word; /* 0x210 */
__u8 pad8[0xc00-0x214]; /* 0x214 */ __u32 diag44_opcode; /* 0x214 */
__u8 pad8[0xc00-0x218]; /* 0x218 */
/* System info area */ /* System info area */
__u64 save_area[16]; /* 0xc00 */ __u64 save_area[16]; /* 0xc00 */
__u8 pad9[0xd40-0xc80]; /* 0xc80 */ __u8 pad9[0xd40-0xc80]; /* 0xc80 */
......
...@@ -28,6 +28,7 @@ extern unsigned long machine_flags; ...@@ -28,6 +28,7 @@ extern unsigned long machine_flags;
#define MACHINE_IS_VM (machine_flags & 1) #define MACHINE_IS_VM (machine_flags & 1)
#define MACHINE_IS_P390 (machine_flags & 4) #define MACHINE_IS_P390 (machine_flags & 4)
#define MACHINE_HAS_MVPG (machine_flags & 16) #define MACHINE_HAS_MVPG (machine_flags & 16)
#define MACHINE_HAS_DIAG44 (machine_flags & 32)
#define MACHINE_HAS_HWC (!MACHINE_IS_P390) #define MACHINE_HAS_HWC (!MACHINE_IS_P390)
......
...@@ -16,7 +16,14 @@ ...@@ -16,7 +16,14 @@
* asm/spinlock.h. The diagnose is only available in kernel * asm/spinlock.h. The diagnose is only available in kernel
* context. * context.
*/ */
#ifdef __KERNEL__
#include <asm/lowcore.h> #include <asm/lowcore.h>
#define __DIAG44_INSN "ex"
#define __DIAG44_OPERAND __LC_DIAG44_OPCODE
#else
#define __DIAG44_INSN "#"
#define __DIAG44_OPERAND 0
#endif
/* /*
* Simple spin lock operations. There are two variants, one clears IRQ's * Simple spin lock operations. There are two variants, one clears IRQ's
...@@ -38,12 +45,13 @@ extern inline void _raw_spin_lock(spinlock_t *lp) ...@@ -38,12 +45,13 @@ extern inline void _raw_spin_lock(spinlock_t *lp)
{ {
unsigned long reg1, reg2; unsigned long reg1, reg2;
__asm__ __volatile(" bras %1,1f\n" __asm__ __volatile(" bras %1,1f\n"
"0: # diag 0,0,68\n" "0: " __DIAG44_INSN " 0,%4\n"
"1: slr %0,%0\n" "1: slr %0,%0\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,0(%3)\n"
" jl 0b\n" " jl 0b\n"
: "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock) : "=&d" (reg1), "=&d" (reg2), "+m" (lp->lock)
: "a" (&lp->lock) : "cc" ); : "a" (&lp->lock), "i" (__DIAG44_OPERAND)
: "cc" );
} }
extern inline int _raw_spin_trylock(spinlock_t *lp) extern inline int _raw_spin_trylock(spinlock_t *lp)
...@@ -88,43 +96,47 @@ typedef struct { ...@@ -88,43 +96,47 @@ typedef struct {
#define _raw_read_lock(rw) \ #define _raw_read_lock(rw) \
asm volatile(" lg 2,0(%1)\n" \ asm volatile(" lg 2,0(%1)\n" \
" j 1f\n" \ " j 1f\n" \
"0: # diag 0,0,68\n" \ "0: " __DIAG44_INSN " 0,%2\n" \
"1: nihh 2,0x7fff\n" /* clear high (=write) bit */ \ "1: nihh 2,0x7fff\n" /* clear high (=write) bit */ \
" la 3,1(2)\n" /* one more reader */ \ " la 3,1(2)\n" /* one more reader */ \
" csg 2,3,0(%1)\n" /* try to write new value */ \ " csg 2,3,0(%1)\n" /* try to write new value */ \
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#define _raw_read_unlock(rw) \ #define _raw_read_unlock(rw) \
asm volatile(" lg 2,0(%1)\n" \ asm volatile(" lg 2,0(%1)\n" \
" j 1f\n" \ " j 1f\n" \
"0: # diag 0,0,68\n" \ "0: " __DIAG44_INSN " 0,%2\n" \
"1: lgr 3,2\n" \ "1: lgr 3,2\n" \
" bctgr 3,0\n" /* one less reader */ \ " bctgr 3,0\n" /* one less reader */ \
" csg 2,3,0(%1)\n" \ " csg 2,3,0(%1)\n" \
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#define _raw_write_lock(rw) \ #define _raw_write_lock(rw) \
asm volatile(" llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \ asm volatile(" llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \
" j 1f\n" \ " j 1f\n" \
"0: # diag 0,0,68\n" \ "0: " __DIAG44_INSN " 0,%2\n" \
"1: slgr 2,2\n" /* old lock value must be 0 */ \ "1: slgr 2,2\n" /* old lock value must be 0 */ \
" csg 2,3,0(%1)\n" \ " csg 2,3,0(%1)\n" \
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#define _raw_write_unlock(rw) \ #define _raw_write_unlock(rw) \
asm volatile(" slgr 3,3\n" /* new lock value = 0 */ \ asm volatile(" slgr 3,3\n" /* new lock value = 0 */ \
" j 1f\n" \ " j 1f\n" \
"0: # diag 0,0,68\n" \ "0: " __DIAG44_INSN " 0,%2\n" \
"1: llihh 2,0x8000\n" /* old lock value must be 0x8..0 */\ "1: llihh 2,0x8000\n" /* old lock value must be 0x8..0 */\
" csg 2,3,0(%1)\n" \ " csg 2,3,0(%1)\n" \
" jl 0b" \ " jl 0b" \
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) \
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" ) : "2", "3", "cc" )
#endif /* __ASM_SPINLOCK_H */ #endif /* __ASM_SPINLOCK_H */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment