aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/entry.S')
-rw-r--r--arch/s390/kernel/entry.S159
1 files changed, 88 insertions, 71 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 3705700ed37..74ee563fe62 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -2,7 +2,7 @@
2 * arch/s390/kernel/entry.S 2 * arch/s390/kernel/entry.S
3 * S390 low-level entry points. 3 * S390 low-level entry points.
4 * 4 *
5 * Copyright (C) IBM Corp. 1999,2006 5 * Copyright (C) IBM Corp. 1999,2012
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 * Hartmut Penner (hp@de.ibm.com), 7 * Hartmut Penner (hp@de.ibm.com),
8 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), 8 * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -105,14 +105,14 @@ STACK_SIZE = 1 << STACK_SHIFT
105 105
106 .macro ADD64 high,low,timer 106 .macro ADD64 high,low,timer
107 al \high,\timer 107 al \high,\timer
108 al \low,\timer+4 108 al \low,4+\timer
109 brc 12,.+8 109 brc 12,.+8
110 ahi \high,1 110 ahi \high,1
111 .endm 111 .endm
112 112
113 .macro SUB64 high,low,timer 113 .macro SUB64 high,low,timer
114 sl \high,\timer 114 sl \high,\timer
115 sl \low,\timer+4 115 sl \low,4+\timer
116 brc 3,.+8 116 brc 3,.+8
117 ahi \high,-1 117 ahi \high,-1
118 .endm 118 .endm
@@ -471,7 +471,6 @@ io_tif:
471 jnz io_work # there is work to do (signals etc.) 471 jnz io_work # there is work to do (signals etc.)
472io_restore: 472io_restore:
473 mvc __LC_RETURN_PSW(8),__PT_PSW(%r11) 473 mvc __LC_RETURN_PSW(8),__PT_PSW(%r11)
474 ni __LC_RETURN_PSW+1,0xfd # clean wait state bit
475 stpt __LC_EXIT_TIMER 474 stpt __LC_EXIT_TIMER
476 lm %r0,%r15,__PT_R0(%r11) 475 lm %r0,%r15,__PT_R0(%r11)
477 lpsw __LC_RETURN_PSW 476 lpsw __LC_RETURN_PSW
@@ -606,12 +605,32 @@ ext_skip:
606 stm %r8,%r9,__PT_PSW(%r11) 605 stm %r8,%r9,__PT_PSW(%r11)
607 TRACE_IRQS_OFF 606 TRACE_IRQS_OFF
608 lr %r2,%r11 # pass pointer to pt_regs 607 lr %r2,%r11 # pass pointer to pt_regs
609 l %r3,__LC_CPU_ADDRESS # get cpu address + interruption code 608 l %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code
610 l %r4,__LC_EXT_PARAMS # get external parameters 609 l %r4,__LC_EXT_PARAMS # get external parameters
611 l %r1,BASED(.Ldo_extint) 610 l %r1,BASED(.Ldo_extint)
612 basr %r14,%r1 # call do_extint 611 basr %r14,%r1 # call do_extint
613 j io_return 612 j io_return
614 613
614/*
615 * Load idle PSW. The second "half" of this function is in cleanup_idle.
616 */
617ENTRY(psw_idle)
618 st %r4,__SF_EMPTY(%r15)
619 basr %r1,0
620 la %r1,psw_idle_lpsw+4-.(%r1)
621 st %r1,__SF_EMPTY+4(%r15)
622 oi __SF_EMPTY+4(%r15),0x80
623 la %r1,.Lvtimer_max-psw_idle_lpsw-4(%r1)
624 stck __IDLE_ENTER(%r2)
625 ltr %r5,%r5
626 stpt __VQ_IDLE_ENTER(%r3)
627 jz psw_idle_lpsw
628 spt 0(%r1)
629psw_idle_lpsw:
630 lpsw __SF_EMPTY(%r15)
631 br %r14
632psw_idle_end:
633
615__critical_end: 634__critical_end:
616 635
617/* 636/*
@@ -673,7 +692,6 @@ mcck_skip:
673 TRACE_IRQS_ON 692 TRACE_IRQS_ON
674mcck_return: 693mcck_return:
675 mvc __LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW 694 mvc __LC_RETURN_MCCK_PSW(8),__PT_PSW(%r11) # move return PSW
676 ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit
677 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? 695 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ?
678 jno 0f 696 jno 0f
679 lm %r0,%r15,__PT_R0(%r11) 697 lm %r0,%r15,__PT_R0(%r11)
@@ -691,77 +709,30 @@ mcck_panic:
6910: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) 7090: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
692 j mcck_skip 710 j mcck_skip
693 711
694/*
695 * Restart interruption handler, kick starter for additional CPUs
696 */
697#ifdef CONFIG_SMP
698 __CPUINIT
699ENTRY(restart_int_handler)
700 basr %r1,0
701restart_base:
702 spt restart_vtime-restart_base(%r1)
703 stck __LC_LAST_UPDATE_CLOCK
704 mvc __LC_LAST_UPDATE_TIMER(8),restart_vtime-restart_base(%r1)
705 mvc __LC_EXIT_TIMER(8),restart_vtime-restart_base(%r1)
706 l %r15,__LC_GPREGS_SAVE_AREA+60 # load ksp
707 lctl %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
708 lam %a0,%a15,__LC_AREGS_SAVE_AREA
709 lm %r6,%r15,__SF_GPRS(%r15)# load registers from clone
710 l %r1,__LC_THREAD_INFO
711 mvc __LC_USER_TIMER(8),__TI_user_timer(%r1)
712 mvc __LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
713 xc __LC_STEAL_TIMER(8),__LC_STEAL_TIMER
714 ssm __LC_PGM_NEW_PSW # turn dat on, keep irqs off
715 basr %r14,0
716 l %r14,restart_addr-.(%r14)
717 basr %r14,%r14 # call start_secondary
718restart_addr:
719 .long start_secondary
720 .align 8
721restart_vtime:
722 .long 0x7fffffff,0xffffffff
723 .previous
724#else
725/*
726 * If we do not run with SMP enabled, let the new CPU crash ...
727 */
728ENTRY(restart_int_handler)
729 basr %r1,0
730restart_base:
731 lpsw restart_crash-restart_base(%r1)
732 .align 8
733restart_crash:
734 .long 0x000a0000,0x00000000
735restart_go:
736#endif
737
738# 712#
739# PSW restart interrupt handler 713# PSW restart interrupt handler
740# 714#
741ENTRY(psw_restart_int_handler) 715ENTRY(restart_int_handler)
742 st %r15,__LC_SAVE_AREA_RESTART 716 st %r15,__LC_SAVE_AREA_RESTART
743 basr %r15,0 717 l %r15,__LC_RESTART_STACK
7440: l %r15,.Lrestart_stack-0b(%r15) # load restart stack
745 l %r15,0(%r15)
746 ahi %r15,-__PT_SIZE # create pt_regs on stack 718 ahi %r15,-__PT_SIZE # create pt_regs on stack
719 xc 0(__PT_SIZE,%r15),0(%r15)
747 stm %r0,%r14,__PT_R0(%r15) 720 stm %r0,%r14,__PT_R0(%r15)
748 mvc __PT_R15(4,%r15),__LC_SAVE_AREA_RESTART 721 mvc __PT_R15(4,%r15),__LC_SAVE_AREA_RESTART
749 mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw 722 mvc __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw
750 ahi %r15,-STACK_FRAME_OVERHEAD 723 ahi %r15,-STACK_FRAME_OVERHEAD # create stack frame on stack
751 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 724 xc 0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
752 basr %r14,0 725 lm %r1,%r3,__LC_RESTART_FN # load fn, parm & source cpu
7531: l %r14,.Ldo_restart-1b(%r14) 726 ltr %r3,%r3 # test source cpu address
754 basr %r14,%r14 727 jm 1f # negative -> skip source stop
755 basr %r14,0 # load disabled wait PSW if 7280: sigp %r4,%r3,1 # sigp sense to source cpu
7562: lpsw restart_psw_crash-2b(%r14) # do_restart returns 729 brc 10,0b # wait for status stored
757 .align 4 7301: basr %r14,%r1 # call function
758.Ldo_restart: 731 stap __SF_EMPTY(%r15) # store cpu address
759 .long do_restart 732 lh %r3,__SF_EMPTY(%r15)
760.Lrestart_stack: 7332: sigp %r4,%r3,5 # sigp stop to current cpu
761 .long restart_stack 734 brc 2,2b
762 .align 8 7353: j 3b
763restart_psw_crash:
764 .long 0x000a0000,0x00000000 + restart_psw_crash
765 736
766 .section .kprobes.text, "ax" 737 .section .kprobes.text, "ax"
767 738
@@ -795,6 +766,8 @@ cleanup_table:
795 .long io_tif + 0x80000000 766 .long io_tif + 0x80000000
796 .long io_restore + 0x80000000 767 .long io_restore + 0x80000000
797 .long io_done + 0x80000000 768 .long io_done + 0x80000000
769 .long psw_idle + 0x80000000
770 .long psw_idle_end + 0x80000000
798 771
799cleanup_critical: 772cleanup_critical:
800 cl %r9,BASED(cleanup_table) # system_call 773 cl %r9,BASED(cleanup_table) # system_call
@@ -813,6 +786,10 @@ cleanup_critical:
813 jl cleanup_io_tif 786 jl cleanup_io_tif
814 cl %r9,BASED(cleanup_table+28) # io_done 787 cl %r9,BASED(cleanup_table+28) # io_done
815 jl cleanup_io_restore 788 jl cleanup_io_restore
789 cl %r9,BASED(cleanup_table+32) # psw_idle
790 jl 0f
791 cl %r9,BASED(cleanup_table+36) # psw_idle_end
792 jl cleanup_idle
8160: br %r14 7930: br %r14
817 794
818cleanup_system_call: 795cleanup_system_call:
@@ -896,7 +873,6 @@ cleanup_io_restore:
896 jhe 0f 873 jhe 0f
897 l %r9,12(%r11) # get saved r11 pointer to pt_regs 874 l %r9,12(%r11) # get saved r11 pointer to pt_regs
898 mvc __LC_RETURN_PSW(8),__PT_PSW(%r9) 875 mvc __LC_RETURN_PSW(8),__PT_PSW(%r9)
899 ni __LC_RETURN_PSW+1,0xfd # clear wait state bit
900 mvc 0(32,%r11),__PT_R8(%r9) 876 mvc 0(32,%r11),__PT_R8(%r9)
901 lm %r0,%r7,__PT_R0(%r9) 877 lm %r0,%r7,__PT_R0(%r9)
9020: lm %r8,%r9,__LC_RETURN_PSW 8780: lm %r8,%r9,__LC_RETURN_PSW
@@ -904,11 +880,52 @@ cleanup_io_restore:
904cleanup_io_restore_insn: 880cleanup_io_restore_insn:
905 .long io_done - 4 + 0x80000000 881 .long io_done - 4 + 0x80000000
906 882
883cleanup_idle:
884 # copy interrupt clock & cpu timer
885 mvc __IDLE_EXIT(8,%r2),__LC_INT_CLOCK
886 mvc __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER
887 chi %r11,__LC_SAVE_AREA_ASYNC
888 je 0f
889 mvc __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
890 mvc __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER
8910: # check if stck has been executed
892 cl %r9,BASED(cleanup_idle_insn)
893 jhe 1f
894 mvc __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2)
895 mvc __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3)
896 j 2f
8971: # check if the cpu timer has been reprogrammed
898 ltr %r5,%r5
899 jz 2f
900 spt __VQ_IDLE_ENTER(%r3)
9012: # account system time going idle
902 lm %r9,%r10,__LC_STEAL_TIMER
903 ADD64 %r9,%r10,__IDLE_ENTER(%r2)
904 SUB64 %r9,%r10,__LC_LAST_UPDATE_CLOCK
905 stm %r9,%r10,__LC_STEAL_TIMER
906 mvc __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2)
907 lm %r9,%r10,__LC_SYSTEM_TIMER
908 ADD64 %r9,%r10,__LC_LAST_UPDATE_TIMER
909 SUB64 %r9,%r10,__VQ_IDLE_ENTER(%r3)
910 stm %r9,%r10,__LC_SYSTEM_TIMER
911 mvc __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3)
912 # prepare return psw
913 n %r8,BASED(cleanup_idle_wait) # clear wait state bit
914 l %r9,24(%r11) # return from psw_idle
915 br %r14
916cleanup_idle_insn:
917 .long psw_idle_lpsw + 0x80000000
918cleanup_idle_wait:
919 .long 0xfffdffff
920
907/* 921/*
908 * Integer constants 922 * Integer constants
909 */ 923 */
910 .align 4 924 .align 4
911.Lnr_syscalls: .long NR_syscalls 925.Lnr_syscalls:
926 .long NR_syscalls
927.Lvtimer_max:
928 .quad 0x7fffffffffffffff
912 929
913/* 930/*
914 * Symbol constants 931 * Symbol constants