From 050276ab8ce9f30c1d2d74c42a349ed54701905f Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Wed, 9 May 2012 16:27:34 +0200 Subject: s390/qdio: remove duplicate defines of data div bits Remove duplicate definition accidentally introduced in 104ea55 and re-group definitions nicely. Signed-off-by: Steffen Maier Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/qdio.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index d75c8e78f7e3..74528e27b37f 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -258,11 +258,6 @@ struct slsb { u8 val[QDIO_MAX_BUFFERS_PER_Q]; } __attribute__ ((packed, aligned(256))); -#define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080 -#define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040 -#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 -#define CHSC_AC2_DATA_DIV_ENABLED 0x0002 - /** * struct qdio_outbuf_state - SBAL related asynchronous operation information * (for communication with upper layer programs) @@ -293,6 +288,8 @@ struct qdio_outbuf_state { #define AC1_SC_QEBSM_AVAILABLE 0x02 /* available for subchannel */ #define AC1_SC_QEBSM_ENABLED 0x01 /* enabled for subchannel */ +#define CHSC_AC2_MULTI_BUFFER_AVAILABLE 0x0080 +#define CHSC_AC2_MULTI_BUFFER_ENABLED 0x0040 #define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 #define CHSC_AC2_DATA_DIV_ENABLED 0x0002 -- cgit v1.2.3 From 1549d13f4c5f0ca77b66bd725287d0b3f877eb6b Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 9 May 2012 16:27:34 +0200 Subject: s390/qdio: Cleanup error handling to drivers Various improvements of qdio error reporting to the upper-layer drivers (qeth, zfcp): - Split QDIO_ERROR_ACTIVATE_CHECK_CONDITION into: QDIO_ERROR_ACTIVATE: qdio termination interrupt QDIO_ERROR_GET_BUF_STATE: QIOASSIST eqbs error QDIO_ERROR_SET_BUF_STATE: QIOASSIST sqbs error Add QDIO_ERROR_FATAL / QDIO_ERROR_TEMPORARY masks to ease recovery decision in upper-layer drivers. - Don't (ab-)use qdio handler errors as return codes for do_QDIO but use standard error codes: -ENOBUFS: temporary target CC=2 condition -EBUSY: unresolved SIGA-W CC=2 busy condition -EIO: I/O error (CC=1, CC=3) - Remove unneeded memory clobber from SIGA-R - Remove EX_TABLE entry on SIGA-W, we want to see these errors Reviewed-by: Ursula Braun Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/qdio.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 74528e27b37f..f039d86adf67 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -325,11 +325,13 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, int, int, unsigned long); /* qdio errors reported to the upper-layer program */ -#define QDIO_ERROR_SIGA_TARGET 0x02 -#define QDIO_ERROR_SIGA_ACCESS_EXCEPTION 0x10 -#define QDIO_ERROR_SIGA_BUSY 0x20 -#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40 -#define QDIO_ERROR_SLSB_STATE 0x80 +#define QDIO_ERROR_ACTIVATE 0x0001 +#define QDIO_ERROR_GET_BUF_STATE 0x0002 +#define QDIO_ERROR_SET_BUF_STATE 0x0004 +#define QDIO_ERROR_SLSB_STATE 0x0100 + +#define QDIO_ERROR_FATAL 0x00ff +#define QDIO_ERROR_TEMPORARY 0xff00 /* for qdio_cleanup */ #define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01 -- cgit v1.2.3 From 5cbeecd6629472c46384779ac139fb6643105dac Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:34 +0200 Subject: s390/compat: select COMPAT_BINFMT_ELF only if BINFMT_ELF is set Fix this: warning: (COMPAT) selects COMPAT_BINFMT_ELF which has unmet direct dependencies (COMPAT && BINFMT_ELF) Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 9015060919a0..39799fac4d7a 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -217,7 +217,7 @@ config COMPAT def_bool y prompt "Kernel support for 31 bit emulation" depends on 64BIT - select COMPAT_BINFMT_ELF + select COMPAT_BINFMT_ELF if BINFMT_ELF select ARCH_WANT_OLD_COMPAT_IPC help Select this option if you want to enable your system kernel to -- cgit v1.2.3 From 63291d401c8ab37d8b9a5456e6cbeeca6b32c702 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:35 +0200 Subject: s390/crypto des: add missing select statement Add missing "select CRYPTO_DES". Fixes this: ERROR: "des_ekey" [arch/s390/crypto/des_s390.ko] undefined! Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/defconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 1957a9dd256d..37d2bf267964 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -155,7 +155,6 @@ CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_CAMELLIA=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DES=m CONFIG_CRYPTO_FCRYPT=m CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_SALSA20=m -- cgit v1.2.3 From 9d0f46af3ead2b38889bea07f1a031c0dfd6020e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:35 +0200 Subject: s390/smp: get rid of compile warning Add missing #ifdep CONFIG_HOTPLUG_CPU to get rid of this one: arch/s390/kernel/smp.c:229:13: warning: 'pcpu_free_lowcore' defined but not used [-Wunused-function] Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f77227669e8..e505458c6899 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -226,6 +226,8 @@ out: return -ENOMEM; } +#ifdef CONFIG_HOTPLUG_CPU + static void pcpu_free_lowcore(struct pcpu *pcpu) { pcpu_sigp_retry(pcpu, sigp_set_prefix, 0); @@ -247,6 +249,8 @@ static void pcpu_free_lowcore(struct pcpu *pcpu) } } +#endif /* CONFIG_HOTPLUG_CPU */ + static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu) { struct _lowcore *lc = pcpu->lowcore; -- cgit v1.2.3 From 54310a2d9e109e1cbe24e41388def33ff0391cd1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:35 +0200 Subject: s390/crash dump: add missing SMP dependency Fix this: arch/s390/kernel/crash_dump.c:296:14: error: 'zfcpdump_save_areas' undeclared (first use in this function) Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 39799fac4d7a..eeaed9be5fda 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -569,7 +569,7 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps" - depends on 64BIT + depends on 64BIT && SMP select KEXEC help Generate crash dump after being started by kexec. -- cgit v1.2.3 From 0de9db37f0dff3bda21b3650ba60a21d3fe70df2 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 9 May 2012 16:27:35 +0200 Subject: s390: initialize backchain for ext_int_handler() To allow correct stack backtraces the backchain for the external interrupt handler is now initialized with zero like it is already done for example by io_int_handler(). Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry64.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 4e1c292fa7e3..6b5ea904e997 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -622,6 +622,7 @@ ext_skip: mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC stmg %r8,%r9,__PT_PSW(%r11) TRACE_IRQS_OFF + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) lghi %r1,4096 lgr %r2,%r11 # pass pointer to pt_regs llgf %r3,__LC_EXT_CPU_ADDR # get cpu address + interruption code -- cgit v1.2.3 From 6022afc060425864c33f4ab62bbe41d20ac85362 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 9 May 2012 16:27:36 +0200 Subject: s390: make sie intercept independent of thread_info HANDLE_SIE_INTERCEPT is called early, use supervisor state and instruction address to decide if the reset of the PSW to sie_loop is required. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry64.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 6b5ea904e997..570c29d9b31b 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -81,16 +81,16 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) .macro HANDLE_SIE_INTERCEPT scratch #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) - tm __TI_flags+6(%r12),_TIF_SIE>>8 - jz .+42 - tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP - jz .+8 - .insn s,0xb2800000,BASED(.Lhost_id) # set host id + tmhh %r8,0x0001 # interrupting from user ? + jnz .+42 lgr \scratch,%r9 slg \scratch,BASED(.Lsie_loop) clg \scratch,BASED(.Lsie_length) - jhe .+10 + jhe .+22 lg %r9,BASED(.Lsie_loop) + tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP + jz .+8 + .insn s,0xb2800000,BASED(.Lhost_id) # set host id #endif .endm -- cgit v1.2.3 From b2a68c235663c65365c4b4424c6e6c5ee90ae3a1 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 9 May 2012 16:27:36 +0200 Subject: s390: allow absolute memory access for /dev/mem Currently dev/mem for s390 provides only real memory access. This means that the CPU prefix pages are swapped. The prefix swap for real memory works as follows: Each CPU owns a prefix register that points to a page aligned memory location "P". If this CPU accesses the address range [0,0x1fff], it is translated by the hardware to [P,P+0x1fff]. Accordingly if this CPU accesses the address range [P,P+0x1fff], it is translated by the hardware to [0,0x1fff]. Therefore, if [P,P+0x1fff] or [0,0x1fff] is read from the current /dev/mem device, the incorrectly swapped memory content is returned. With this patch the /dev/mem architecture code is modified to provide absolute memory access. This is done via the arch specific functions xlate_dev_mem_ptr() and unxlate_dev_mem_ptr(). For swapped pages on s390 the function xlate_dev_mem_ptr() now returns a new buffer with a copy of the requested absolute memory. In case the buffer was allocated, the unxlate_dev_mem_ptr() function frees it after /dev/mem code has called copy_to_user(). Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/io.h | 7 ++--- arch/s390/mm/maccess.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index b7ff6afc3caa..27216d317991 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h @@ -38,11 +38,8 @@ static inline void * phys_to_virt(unsigned long address) return (void *) address; } -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) +void *xlate_dev_mem_ptr(unsigned long phys); +void unxlate_dev_mem_ptr(unsigned long phys, void *addr); /* * Convert a virtual cached pointer to an uncached pointer diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index e1335dc2b1b7..795a0a9bb2eb 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -12,6 +12,7 @@ #include #include #include +#include #include /* @@ -166,3 +167,69 @@ out: free_page((unsigned long) buf); return rc; } + +/* + * Check if physical address is within prefix or zero page + */ +static int is_swapped(unsigned long addr) +{ + unsigned long lc; + int cpu; + + if (addr < sizeof(struct _lowcore)) + return 1; + for_each_online_cpu(cpu) { + lc = (unsigned long) lowcore_ptr[cpu]; + if (addr > lc + sizeof(struct _lowcore) - 1 || addr < lc) + continue; + return 1; + } + return 0; +} + +/* + * Return swapped prefix or zero page address + */ +static unsigned long get_swapped(unsigned long addr) +{ + unsigned long prefix = store_prefix(); + + if (addr < sizeof(struct _lowcore)) + return addr + prefix; + if (addr >= prefix && addr < prefix + sizeof(struct _lowcore)) + return addr - prefix; + return addr; +} + +/* + * Convert a physical pointer for /dev/mem access + * + * For swapped prefix pages a new buffer is returned that contains a copy of + * the absolute memory. The buffer size is maximum one page large. + */ +void *xlate_dev_mem_ptr(unsigned long addr) +{ + void *bounce = (void *) addr; + unsigned long size; + + get_online_cpus(); + preempt_disable(); + if (is_swapped(addr)) { + size = PAGE_SIZE - (addr & ~PAGE_MASK); + bounce = (void *) __get_free_page(GFP_ATOMIC); + if (bounce) + memcpy_real(bounce, (void *) get_swapped(addr), size); + } + preempt_enable(); + put_online_cpus(); + return bounce; +} + +/* + * Free converted buffer for /dev/mem access (if necessary) + */ +void unxlate_dev_mem_ptr(unsigned long addr, void *buf) +{ + if ((void *) addr != buf) + free_page((unsigned long) buf); +} -- cgit v1.2.3 From 5e8010cb50d3de7202641c0088c211f7c9593ebc Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 3 May 2012 15:50:44 +0200 Subject: s390: replace TIF_SIE with PF_VCPU Replace the check for TIF_SIE in the fault handler by a check for PF_VCPU. With the last user of TIF_SIE gone we can now remove the bit. Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/thread_info.h | 2 -- arch/s390/kernel/entry64.S | 3 --- arch/s390/mm/fault.c | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index a73038155e0d..003b04edcff6 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -95,7 +95,6 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ #define TIF_SECCOMP 10 /* secure computing */ #define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */ -#define TIF_SIE 12 /* guest execution active */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_31BIT 17 /* 32bit process */ @@ -114,7 +113,6 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SYSCALL_AUDIT (1<>8 sie_loop: lg %r14,__LC_THREAD_INFO # pointer thread_info struct tm __TI_flags+7(%r14),_TIF_EXIT_SIE @@ -986,7 +985,6 @@ sie_done: lg %r14,__LC_THREAD_INFO # pointer thread_info struct sie_exit: lctlg %c1,%c1,__LC_USER_ASCE # load primary asce - ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) lg %r14,__SF_EMPTY+8(%r15) # load guest register save area stmg %r0,%r13,0(%r14) # save guest gprs 0-13 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers @@ -995,7 +993,6 @@ sie_exit: sie_fault: lctlg %c1,%c1,__LC_USER_ASCE # load primary asce lg %r14,__LC_THREAD_INFO # pointer thread_info struct - ni __TI_flags+6(%r14),255-(_TIF_SIE>>8) lg %r14,__SF_EMPTY+8(%r15) # load guest register save area stmg %r0,%r13,0(%r14) # save guest gprs 0-13 lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 46ef3fd0663b..b9aeaca26d3a 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -294,7 +294,7 @@ static inline int do_exception(struct pt_regs *regs, int access) down_read(&mm->mmap_sem); #ifdef CONFIG_PGSTE - if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) { + if ((current->flags & PF_VCPU) && S390_lowcore.gmap) { address = __gmap_fault(address, (struct gmap *) S390_lowcore.gmap); if (address == -EFAULT) { -- cgit v1.2.3 From a686425b31bb6441f6e20d698bf31dc65043f61f Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Wed, 9 May 2012 16:27:37 +0200 Subject: s390/hugepages: clear page table for sw large page emulation The software large page emulation on s390 did not clear the the pre-allocated page table in arch_release_hugepage() before freeing it. This could trigger the WARN_ON(!pte_none(*pte) in mm/vmalloc.c:106 and make vmap_pte_range() fail, because the page table could be reused in page_table_alloc(). This is fixed now by calling clear_table() before page_table_free(). Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/mm/hugetlbpage.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index 597bb2d27c3c..900de2b3cf28 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c @@ -58,6 +58,8 @@ void arch_release_hugepage(struct page *page) ptep = (pte_t *) page[1].index; if (!ptep) return; + clear_table((unsigned long *) ptep, _PAGE_TYPE_EMPTY, + PTRS_PER_PTE * sizeof(pte_t)); page_table_free(&init_mm, (unsigned long *) ptep); page[1].index = 0; } -- cgit v1.2.3 From c15787a7c3f702c4240708fb8e63abce1bfe1136 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Fri, 4 May 2012 09:46:04 +0200 Subject: s390: remove dead code from signal handler The code in entry[64].S calls do_signal only on return to user space. user_mode(regs) is true for every calls to do_signal, it is unnecessary to recheck user_mode at the start of do_signal and the legacy signal stack switching path in get_sigframe is never reached. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/compat_signal.c | 7 ------- arch/s390/kernel/signal.c | 16 ---------------- 2 files changed, 23 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 28040fd5e8a2..377c096ca4a7 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -437,13 +437,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) sp = current->sas_ss_sp + current->sas_ss_size; } - /* This is the legacy signal stack switching. */ - else if (!user_mode(regs) && - !(ka->sa.sa_flags & SA_RESTORER) && - ka->sa.sa_restorer) { - sp = (unsigned long) ka->sa.sa_restorer; - } - return (void __user *)((sp - frame_size) & -8ul); } diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index f7582b27f600..8a4e2b760d56 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -235,13 +235,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) sp = current->sas_ss_sp + current->sas_ss_size; } - /* This is the legacy signal stack switching. */ - else if (!user_mode(regs) && - !(ka->sa.sa_flags & SA_RESTORER) && - ka->sa.sa_restorer) { - sp = (unsigned long) ka->sa.sa_restorer; - } - return (void __user *)((sp - frame_size) & -8ul); } @@ -414,15 +407,6 @@ void do_signal(struct pt_regs *regs) struct k_sigaction ka; sigset_t *oldset; - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else -- cgit v1.2.3 From 58770be6cc5901bfbb908d9c6d8ca679fc55df26 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:38 +0200 Subject: s390/ipl: remove builtin tape ipl code Remove the builtin tape ipl code. If somebody really wants to create a tape which can be ipl'ed from, then this can be achieved by using zipl. zipl can write an ipl record to a tape device and aftwards the kernel image must be written to tape. The steps are described in the "Linux on System z - Device Drivers, Features, and Commands" book (SC33-8411). Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 27 ----------- arch/s390/kernel/head.S | 123 ------------------------------------------------ 2 files changed, 150 deletions(-) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index eeaed9be5fda..354c0fe72ae3 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -406,33 +406,6 @@ config CHSC_SCH comment "Misc" -config IPL - def_bool y - prompt "Builtin IPL record support" - help - If you want to use the produced kernel to IPL directly from a - device, you have to merge a bootsector specific to the device - into the first bytes of the kernel. You will have to select the - IPL device. - -choice - prompt "IPL method generated into head.S" - depends on IPL - default IPL_VM - help - Select "tape" if you want to IPL the image from a Tape. - - Select "vm_reader" if you are running under VM/ESA and want - to IPL the image from the emulated card reader. - -config IPL_TAPE - bool "tape" - -config IPL_VM - bool "vm_reader" - -endchoice - source "fs/Kconfig.binfmt" config FORCE_MAX_ZONEORDER diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index adccd908ebc7..4939d15375aa 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -34,125 +34,7 @@ #endif __HEAD -#ifndef CONFIG_IPL - .org 0 - .long 0x00080000,0x80000000+startup # Just a restart PSW -#else -#ifdef CONFIG_IPL_TAPE -#define IPL_BS 1024 - .org 0 - .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded - .long 0x27000000,0x60000001 # by ipl to addresses 0-23. - .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). - .long 0x00000000,0x00000000 # external old psw - .long 0x00000000,0x00000000 # svc old psw - .long 0x00000000,0x00000000 # program check old psw - .long 0x00000000,0x00000000 # machine check old psw - .long 0x00000000,0x00000000 # io old psw - .long 0x00000000,0x00000000 - .long 0x00000000,0x00000000 - .long 0x00000000,0x00000000 - .long 0x000a0000,0x00000058 # external new psw - .long 0x000a0000,0x00000060 # svc new psw - .long 0x000a0000,0x00000068 # program check new psw - .long 0x000a0000,0x00000070 # machine check new psw - .long 0x00080000,0x80000000+.Lioint # io new psw - .org 0x100 -# -# subroutine for loading from tape -# Parameters: -# R1 = device number -# R2 = load address -.Lloader: - st %r14,.Lldret - la %r3,.Lorbread # r3 = address of orb - la %r5,.Lirb # r5 = address of irb - st %r2,.Lccwread+4 # initialize CCW data addresses - lctl %c6,%c6,.Lcr6 - slr %r2,%r2 -.Lldlp: - la %r6,3 # 3 retries -.Lssch: - ssch 0(%r3) # load chunk of IPL_BS bytes - bnz .Llderr -.Lw4end: - bas %r14,.Lwait4io - tm 8(%r5),0x82 # do we have a problem ? - bnz .Lrecov - slr %r7,%r7 - icm %r7,3,10(%r5) # get residual count - lcr %r7,%r7 - la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read - ar %r2,%r7 # add to total size - tm 8(%r5),0x01 # found a tape mark ? - bnz .Ldone - l %r0,.Lccwread+4 # update CCW data addresses - ar %r0,%r7 - st %r0,.Lccwread+4 - b .Lldlp -.Ldone: - l %r14,.Lldret - br %r14 # r2 contains the total size -.Lrecov: - bas %r14,.Lsense # do the sensing - bct %r6,.Lssch # dec. retry count & branch - b .Llderr -# -# Sense subroutine -# -.Lsense: - st %r14,.Lsnsret - la %r7,.Lorbsense - ssch 0(%r7) # start sense command - bnz .Llderr - bas %r14,.Lwait4io - l %r14,.Lsnsret - tm 8(%r5),0x82 # do we have a problem ? - bnz .Llderr - br %r14 -# -# Wait for interrupt subroutine -# -.Lwait4io: - lpsw .Lwaitpsw -.Lioint: - c %r1,0xb8 # compare subchannel number - bne .Lwait4io - tsch 0(%r5) - slr %r0,%r0 - tm 8(%r5),0x82 # do we have a problem ? - bnz .Lwtexit - tm 8(%r5),0x04 # got device end ? - bz .Lwait4io -.Lwtexit: - br %r14 -.Llderr: - lpsw .Lcrash - - .align 8 -.Lorbread: - .long 0x00000000,0x0080ff00,.Lccwread - .align 8 -.Lorbsense: - .long 0x00000000,0x0080ff00,.Lccwsense - .align 8 -.Lccwread: - .long 0x02200000+IPL_BS,0x00000000 -.Lccwsense: - .long 0x04200001,0x00000000 -.Lwaitpsw: - .long 0x020a0000,0x80000000+.Lioint - -.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -.Lcr6: .long 0xff000000 - .align 8 -.Lcrash:.long 0x000a0000,0x00000000 -.Lldret:.long 0 -.Lsnsret: .long 0 -#endif /* CONFIG_IPL_TAPE */ - -#ifdef CONFIG_IPL_VM #define IPL_BS 0x730 .org 0 .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded @@ -256,7 +138,6 @@ __HEAD .long 0x02600050,0x00000000 .endr .long 0x02200050,0x00000000 -#endif /* CONFIG_IPL_VM */ iplstart: lh %r1,0xb8 # test if subchannel number @@ -325,7 +206,6 @@ iplstart: clc 0(3,%r2),.L_eof bz .Lagain2 -#ifdef CONFIG_IPL_VM # # reset files in VM reader # @@ -358,7 +238,6 @@ iplstart: .long 0x00080000,0x80000000+.Lrdrint .Lrdrwaitpsw: .long 0x020a0000,0x80000000+.Lrdrint -#endif # # everything loaded, go for it @@ -376,8 +255,6 @@ iplstart: .L_eof: .long 0xc5d6c600 /* C'EOF' */ .L_hdr: .long 0xc8c4d900 /* C'HDR' */ -#endif /* CONFIG_IPL */ - # # SALIPL loader support. Based on a patch by Rob van der Heij. # This entry point is called directly from the SALIPL loader and -- cgit v1.2.3 From ae73c76ab706a4f8d7e0bf92273242e7e1b43772 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:38 +0200 Subject: s390: add various .gitignore files. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/boot/.gitignore | 2 ++ arch/s390/boot/compressed/.gitignore | 3 +++ arch/s390/kernel/.gitignore | 1 + arch/s390/kernel/vdso32/.gitignore | 1 + arch/s390/kernel/vdso64/.gitignore | 1 + 5 files changed, 8 insertions(+) create mode 100644 arch/s390/boot/.gitignore create mode 100644 arch/s390/boot/compressed/.gitignore create mode 100644 arch/s390/kernel/.gitignore create mode 100644 arch/s390/kernel/vdso32/.gitignore create mode 100644 arch/s390/kernel/vdso64/.gitignore (limited to 'arch') diff --git a/arch/s390/boot/.gitignore b/arch/s390/boot/.gitignore new file mode 100644 index 000000000000..017d5912ad2d --- /dev/null +++ b/arch/s390/boot/.gitignore @@ -0,0 +1,2 @@ +image +bzImage diff --git a/arch/s390/boot/compressed/.gitignore b/arch/s390/boot/compressed/.gitignore new file mode 100644 index 000000000000..ae06b9b4c02f --- /dev/null +++ b/arch/s390/boot/compressed/.gitignore @@ -0,0 +1,3 @@ +sizes.h +vmlinux +vmlinux.lds diff --git a/arch/s390/kernel/.gitignore b/arch/s390/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/s390/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds diff --git a/arch/s390/kernel/vdso32/.gitignore b/arch/s390/kernel/vdso32/.gitignore new file mode 100644 index 000000000000..e45fba9d0ced --- /dev/null +++ b/arch/s390/kernel/vdso32/.gitignore @@ -0,0 +1 @@ +vdso32.lds diff --git a/arch/s390/kernel/vdso64/.gitignore b/arch/s390/kernel/vdso64/.gitignore new file mode 100644 index 000000000000..3fd18cf9fec2 --- /dev/null +++ b/arch/s390/kernel/vdso64/.gitignore @@ -0,0 +1 @@ +vdso64.lds -- cgit v1.2.3 From 2739b6d12407792f253b7a15233930338e6831c9 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 9 May 2012 16:27:38 +0200 Subject: s390/kvm: bad rss-counter state commit c3f0327f8e9d7a503f0d64573c311eddd61f197d mm: add rss counters consistency check detected the following problem with kvm on s390: BUG: Bad rss-counter state mm:00000004f73ef000 idx:0 val:-10 BUG: Bad rss-counter state mm:00000004f73ef000 idx:1 val:-5 We have to make sure that we accumulate all rss values into the mm before we replace the mm to avoid triggering this (harmless) bug message. Signed-off-by: Christian Borntraeger Signed-off-by: Martin Schwidefsky --- arch/s390/mm/pgtable.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6e765bf00670..a3db5a3ea083 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -822,6 +822,8 @@ int s390_enable_sie(void) /* we copy the mm and let dup_mm create the page tables with_pgstes */ tsk->mm->context.alloc_pgste = 1; + /* make sure that both mms have a correct rss state */ + sync_mm_rss(tsk->mm); mm = dup_mm(tsk); tsk->mm->context.alloc_pgste = 0; if (!mm) -- cgit v1.2.3 From 473e66baad1e83e6c5dfdca65aba03bf21727202 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 16:27:39 +0200 Subject: s390/time: always use stckf instead of stck if available The store clock fast instruction saves a couple of instructions compared to the store clock instruction. Always use stckf instead of stck if it is available. Signed-off-by: Heiko Carstens Reviewed-by: Martin Schwidefsky Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/setup.h | 3 --- arch/s390/include/asm/timex.h | 17 +++++------------ arch/s390/kernel/early.c | 2 -- arch/s390/kernel/entry64.S | 16 ++++++++++++---- 4 files changed, 17 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index b21e46e5d4b8..7244e1f64126 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -82,7 +82,6 @@ extern unsigned int user_mode; #define MACHINE_FLAG_LPAR (1UL << 12) #define MACHINE_FLAG_SPP (1UL << 13) #define MACHINE_FLAG_TOPOLOGY (1UL << 14) -#define MACHINE_FLAG_STCKF (1UL << 15) #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) @@ -101,7 +100,6 @@ extern unsigned int user_mode; #define MACHINE_HAS_PFMF (0) #define MACHINE_HAS_SPP (0) #define MACHINE_HAS_TOPOLOGY (0) -#define MACHINE_HAS_STCKF (0) #else /* __s390x__ */ #define MACHINE_HAS_IEEE (1) #define MACHINE_HAS_CSP (1) @@ -113,7 +111,6 @@ extern unsigned int user_mode; #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) #define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) #define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) -#define MACHINE_HAS_STCKF (S390_lowcore.machine_flags & MACHINE_FLAG_STCKF) #endif /* __s390x__ */ #define ZFCPDUMP_HSA_SIZE (32UL<<20) diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index c447a27a7fdb..72eaa8511a4f 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -73,11 +73,15 @@ static inline void local_tick_enable(unsigned long long comp) typedef unsigned long long cycles_t; -static inline unsigned long long get_clock (void) +static inline unsigned long long get_clock(void) { unsigned long long clk; +#if defined(CONFIG_64BIT) && !defined(CONFIG_MARCH_Z900) && !defined(CONFIG_MARCH_Z990) + asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc"); +#else asm volatile("stck %0" : "=Q" (clk) : : "cc"); +#endif return clk; } @@ -86,17 +90,6 @@ static inline void get_clock_ext(char *clk) asm volatile("stcke %0" : "=Q" (*clk) : : "cc"); } -static inline unsigned long long get_clock_fast(void) -{ - unsigned long long clk; - - if (MACHINE_HAS_STCKF) - asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc"); - else - clk = get_clock(); - return clk; -} - static inline unsigned long long get_clock_xt(void) { unsigned char clk[16]; diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 9475e682727f..d84181f1f5e8 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -374,8 +374,6 @@ static __init void detect_machine_facilities(void) S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; if (test_facility(40)) S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; - if (test_facility(25)) - S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF; #endif } diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 3a633af72bae..444fd72e0787 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -148,6 +148,14 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) ssm __LC_RETURN_PSW .endm + .macro STCK savearea +#if defined(CONFIG_64BIT) && !defined(CONFIG_MARCH_Z900) && !defined(CONFIG_MARCH_Z990) + .insn s,0xb27c0000,\savearea # store clock fast +#else + .insn s,0xb2050000,\savearea # store clock +#endif + .endm + .section .kprobes.text, "ax" /* @@ -458,7 +466,7 @@ pgm_svcper: * IO interrupt handler routine */ ENTRY(io_int_handler) - stck __LC_INT_CLOCK + STCK __LC_INT_CLOCK stpt __LC_ASYNC_ENTER_TIMER stmg %r8,%r15,__LC_SAVE_AREA_ASYNC lg %r10,__LC_LAST_BREAK @@ -604,7 +612,7 @@ io_notify_resume: * External interrupt handler routine */ ENTRY(ext_int_handler) - stck __LC_INT_CLOCK + STCK __LC_INT_CLOCK stpt __LC_ASYNC_ENTER_TIMER stmg %r8,%r15,__LC_SAVE_AREA_ASYNC lg %r10,__LC_LAST_BREAK @@ -639,7 +647,7 @@ ENTRY(psw_idle) larl %r1,psw_idle_lpsw+4 stg %r1,__SF_EMPTY+8(%r15) larl %r1,.Lvtimer_max - stck __IDLE_ENTER(%r2) + STCK __IDLE_ENTER(%r2) ltr %r5,%r5 stpt __VQ_IDLE_ENTER(%r3) jz psw_idle_lpsw @@ -655,7 +663,7 @@ __critical_end: * Machine check handler routines */ ENTRY(mcck_int_handler) - stck __LC_MCCK_CLOCK + STCK __LC_MCCK_CLOCK la %r1,4095 # revalidate r1 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs -- cgit v1.2.3 From d5e50a51ccbda36b379aba9d1131a852eb908dda Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 9 May 2012 09:37:30 +0200 Subject: s390/pfault: fix task state race When setting the current task state to TASK_UNINTERRUPTIBLE this can race with a different cpu. The other cpu could set the task state after it inspected it (while it was still TASK_RUNNING) to TASK_RUNNING which would change the state from TASK_UNINTERRUPTIBLE to TASK_RUNNING again. This race was always present in the pfault interrupt code but didn't cause anything harmful before commit f2db2e6c "[S390] pfault: cpu hotplug vs missing completion interrupts" which relied on the fact that after setting the task state to TASK_UNINTERRUPTIBLE the task would really sleep. Since this is not necessarily the case the result may be a list corruption of the pfault_list or, as observed, a use-after-free bug while trying to access the task_struct of a task which terminated itself already. To fix this, we need to get a reference of the affected task when receiving the initial pfault interrupt and add special handling if we receive yet another initial pfault interrupt when the task is already enqueued in the pfault list. Signed-off-by: Heiko Carstens Reviewed-by: Martin Schwidefsky Cc: # needed for v3.0 and newer Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index b9aeaca26d3a..67e2d4d14ae6 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -574,6 +574,7 @@ static void pfault_interrupt(struct ext_code ext_code, tsk->thread.pfault_wait = 0; list_del(&tsk->thread.list); wake_up_process(tsk); + put_task_struct(tsk); } else { /* Completion interrupt was faster than initial * interrupt. Set pfault_wait to -1 so the initial @@ -588,14 +589,22 @@ static void pfault_interrupt(struct ext_code ext_code, put_task_struct(tsk); } else { /* signal bit not set -> a real page is missing. */ - if (tsk->thread.pfault_wait == -1) { + if (tsk->thread.pfault_wait == 1) { + /* Already on the list with a reference: put to sleep */ + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + set_tsk_need_resched(tsk); + } else if (tsk->thread.pfault_wait == -1) { /* Completion interrupt was faster than the initial * interrupt (pfault_wait == -1). Set pfault_wait * back to zero and exit. */ tsk->thread.pfault_wait = 0; } else { /* Initial interrupt arrived before completion - * interrupt. Let the task sleep. */ + * interrupt. Let the task sleep. + * An extra task reference is needed since a different + * cpu may set the task state to TASK_RUNNING again + * before the scheduler is reached. */ + get_task_struct(tsk); tsk->thread.pfault_wait = 1; list_add(&tsk->thread.list, &pfault_list); set_task_state(tsk, TASK_UNINTERRUPTIBLE); @@ -620,6 +629,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self, list_del(&thread->list); tsk = container_of(thread, struct task_struct, thread); wake_up_process(tsk); + put_task_struct(tsk); } spin_unlock_irq(&pfault_lock); break; -- cgit v1.2.3 From 54c27791227756b37504bd35b9ad0a40d1ae4c4b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 10 May 2012 09:44:35 +0200 Subject: s390/pfault: always search for task with reported pid Make the code a bit more symmetric and always search for the task of the reported pid. This simplifies the code a bit. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 67e2d4d14ae6..4306f5e75a33 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -549,19 +549,15 @@ static void pfault_interrupt(struct ext_code ext_code, if ((subcode & 0xff00) != __SUBCODE_MASK) return; kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; - if (subcode & 0x0080) { - /* Get the token (= pid of the affected task). */ - pid = sizeof(void *) == 4 ? param32 : param64; - rcu_read_lock(); - tsk = find_task_by_pid_ns(pid, &init_pid_ns); - if (tsk) - get_task_struct(tsk); - rcu_read_unlock(); - if (!tsk) - return; - } else { - tsk = current; - } + /* Get the token (= pid of the affected task). */ + pid = sizeof(void *) == 4 ? param32 : param64; + rcu_read_lock(); + tsk = find_task_by_pid_ns(pid, &init_pid_ns); + if (tsk) + get_task_struct(tsk); + rcu_read_unlock(); + if (!tsk) + return; spin_lock(&pfault_lock); if (subcode & 0x0080) { /* signal bit is set -> a page has been swapped in by VM */ @@ -586,7 +582,6 @@ static void pfault_interrupt(struct ext_code ext_code, if (tsk->state == TASK_RUNNING) tsk->thread.pfault_wait = -1; } - put_task_struct(tsk); } else { /* signal bit not set -> a real page is missing. */ if (tsk->thread.pfault_wait == 1) { @@ -612,6 +607,7 @@ static void pfault_interrupt(struct ext_code ext_code, } } spin_unlock(&pfault_lock); + put_task_struct(tsk); } static int __cpuinit pfault_cpu_notify(struct notifier_block *self, -- cgit v1.2.3 From 0a16ba7866fd5cd802d49801a099f4c558ce99c7 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 10 May 2012 09:56:34 +0200 Subject: s390/pfault: use __set_task_state Use __set_task_state() instead of set_task_state(). Saves a couple of instructions, since the memory barrier is not needed here. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 4306f5e75a33..a9c11aa57450 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -586,7 +586,7 @@ static void pfault_interrupt(struct ext_code ext_code, /* signal bit not set -> a real page is missing. */ if (tsk->thread.pfault_wait == 1) { /* Already on the list with a reference: put to sleep */ - set_task_state(tsk, TASK_UNINTERRUPTIBLE); + __set_task_state(tsk, TASK_UNINTERRUPTIBLE); set_tsk_need_resched(tsk); } else if (tsk->thread.pfault_wait == -1) { /* Completion interrupt was faster than the initial @@ -602,7 +602,7 @@ static void pfault_interrupt(struct ext_code ext_code, get_task_struct(tsk); tsk->thread.pfault_wait = 1; list_add(&tsk->thread.list, &pfault_list); - set_task_state(tsk, TASK_UNINTERRUPTIBLE); + __set_task_state(tsk, TASK_UNINTERRUPTIBLE); set_tsk_need_resched(tsk); } } -- cgit v1.2.3 From d49f47f83d15f3142d482a29de76f45360e34082 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 10 May 2012 10:47:21 +0200 Subject: s390/pfault: add sanity check If the task that was found on an initial interrupt doesn't match the current task execute a WARN_ON_ONCE() and don't put the task to sleep. When this happened something went wrong between the interface of the hypervisor and the kernel. In such a case keep the tasks alive to avoid a hanging system. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index a9c11aa57450..72cec9ecd96c 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -584,6 +584,8 @@ static void pfault_interrupt(struct ext_code ext_code, } } else { /* signal bit not set -> a real page is missing. */ + if (WARN_ON_ONCE(tsk != current)) + goto out; if (tsk->thread.pfault_wait == 1) { /* Already on the list with a reference: put to sleep */ __set_task_state(tsk, TASK_UNINTERRUPTIBLE); @@ -606,6 +608,7 @@ static void pfault_interrupt(struct ext_code ext_code, set_tsk_need_resched(tsk); } } +out: spin_unlock(&pfault_lock); put_task_struct(tsk); } -- cgit v1.2.3 From 9ee39e4b840d54f0127cd4ef607da79469917888 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 May 2012 10:09:43 +0200 Subject: s390/entry64: avoid SPP code duplication Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 444fd72e0787..02b660a7dcd4 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -88,9 +88,7 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) clg \scratch,BASED(.Lsie_length) jhe .+22 lg %r9,BASED(.Lsie_loop) - tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP - jz .+8 - .insn s,0xb2800000,BASED(.Lhost_id) # set host id + SPP BASED(.Lhost_id) # set host id #endif .endm -- cgit v1.2.3 From 0544516956c0b949e3190f744df4b473f5ad4853 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 May 2012 10:12:41 +0200 Subject: s390/Kconfig: add HAVE_MARCH_[ARCH]_FEATURES Kconfig symbols Add HAVE_MARCH_[ARCH]_FEATURES Kconfig symbols. Whenever there is code that needs an instruction that is only present beginning with a hardware generation the #ifdef chain can become quite long. To avoid this add the new Kconfig symbols which are selected if the kernel gets compiled for at least the specified symbol. If for example the kernel gets compiled for z196 this means that also all symbols for all previous architure features are set. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 354c0fe72ae3..b42f2866594b 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -234,6 +234,25 @@ config KEYS_COMPAT config AUDIT_ARCH def_bool y +config HAVE_MARCH_Z900_FEATURES + def_bool n + +config HAVE_MARCH_Z990_FEATURES + def_bool n + select HAVE_MARCH_Z900_FEATURES + +config HAVE_MARCH_Z9_109_FEATURES + def_bool n + select HAVE_MARCH_Z990_FEATURES + +config HAVE_MARCH_Z10_FEATURES + def_bool n + select HAVE_MARCH_Z9_109_FEATURES + +config HAVE_MARCH_Z196_FEATURES + def_bool n + select HAVE_MARCH_Z10_FEATURES + comment "Code generation options" choice @@ -249,6 +268,7 @@ config MARCH_G5 config MARCH_Z900 bool "IBM zSeries model z800 and z900" + select HAVE_MARCH_Z900_FEATURES if 64BIT help Select this to enable optimizations for model z800/z900 (2064 and 2066 series). This will enable some optimizations that are not @@ -256,6 +276,7 @@ config MARCH_Z900 config MARCH_Z990 bool "IBM zSeries model z890 and z990" + select HAVE_MARCH_Z990_FEATURES if 64BIT help Select this to enable optimizations for model z890/z990 (2084 and 2086 series). The kernel will be slightly faster but will not work @@ -263,6 +284,7 @@ config MARCH_Z990 config MARCH_Z9_109 bool "IBM System z9" + select HAVE_MARCH_Z9_109_FEATURES if 64BIT help Select this to enable optimizations for IBM System z9 (2094 and 2096 series). The kernel will be slightly faster but will not work @@ -270,6 +292,7 @@ config MARCH_Z9_109 config MARCH_Z10 bool "IBM System z10" + select HAVE_MARCH_Z10_FEATURES if 64BIT help Select this to enable optimizations for IBM System z10 (2097 and 2098 series). The kernel will be slightly faster but will not work @@ -277,6 +300,7 @@ config MARCH_Z10 config MARCH_Z196 bool "IBM zEnterprise 114 and 196" + select HAVE_MARCH_Z196_FEATURES if 64BIT help Select this to enable optimizations for IBM zEnterprise 114 and 196 (2818 and 2817 series). The kernel will be slightly faster but will -- cgit v1.2.3 From d652d59682c8891bdaecfccc72b0209cbe91d89f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 May 2012 10:35:22 +0200 Subject: s390/time: simply Kconfig dependency Use HAVE_MARCH_Z9_109_FEATURES to figure out if stckf is available at compile time. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/timex.h | 2 +- arch/s390/kernel/entry64.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 72eaa8511a4f..239ece9e53c1 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -77,7 +77,7 @@ static inline unsigned long long get_clock(void) { unsigned long long clk; -#if defined(CONFIG_64BIT) && !defined(CONFIG_MARCH_Z900) && !defined(CONFIG_MARCH_Z990) +#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc"); #else asm volatile("stck %0" : "=Q" (clk) : : "cc"); diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 02b660a7dcd4..02bf601d84bf 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -147,7 +147,7 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) .endm .macro STCK savearea -#if defined(CONFIG_64BIT) && !defined(CONFIG_MARCH_Z900) && !defined(CONFIG_MARCH_Z990) +#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES .insn s,0xb27c0000,\savearea # store clock fast #else .insn s,0xb2050000,\savearea # store clock -- cgit v1.2.3 From c6f48b0bbeba86f12847b16b1d4631363037f7f3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 May 2012 12:40:43 +0200 Subject: s390/barrier: cleanup barrier functions s390 really has no eieio instruction, so get rid of the implied ppc semantics and in addition change mb() into a function. Also remove SYNC_OTHER_CORES() since it is unused. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/barrier.h | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h index 451273ad4d34..6993b20d64fb 100644 --- a/arch/s390/include/asm/barrier.h +++ b/arch/s390/include/asm/barrier.h @@ -11,25 +11,23 @@ * 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" : : : "memory") -#define SYNC_OTHER_CORES(x) eieio() -#define mb() eieio() -#define rmb() eieio() -#define wmb() eieio() -#define read_barrier_depends() do { } while(0) -#define smp_mb() mb() -#define smp_rmb() rmb() -#define smp_wmb() wmb() -#define smp_read_barrier_depends() read_barrier_depends() -#define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() smp_mb() +static inline void mb(void) +{ + asm volatile("bcr 15,0" : : : "memory"); +} + +#define rmb() mb() +#define wmb() mb() +#define read_barrier_depends() do { } while(0) +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() +#define smp_read_barrier_depends() read_barrier_depends() +#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_mb(var, value) do { var = value; mb(); } while (0) #endif /* __ASM_BARRIER_H */ -- cgit v1.2.3 From e5b8d7553f87d939295e9eb0ca699c0030dc5ff1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 14 May 2012 12:41:54 +0200 Subject: s390/barrier: make use of fast-bcr facility If the kernel gets compiled for at least z196, make use of the fast-BCR facility. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/barrier.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h index 6993b20d64fb..10a508802940 100644 --- a/arch/s390/include/asm/barrier.h +++ b/arch/s390/include/asm/barrier.h @@ -15,7 +15,12 @@ static inline void mb(void) { +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES + /* Fast-BCR without checkpoint synchronization */ + asm volatile("bcr 14,0" : : : "memory"); +#else asm volatile("bcr 15,0" : : : "memory"); +#endif } #define rmb() mb() -- cgit v1.2.3 From eda0c6d6b04d3cf72f5e8d656e39bffe3568e6db Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 15 May 2012 09:20:06 +0200 Subject: s390: fix race on TIF_MCCK_PENDING There is a small race window in the __switch_to code in regard to the transfer of the TIF_MCCK_PENDING bit from the previous to the next task. The bit is transferred before the task struct pointer and the thread-info pointer for the next task has been stored to lowcore. If a machine check sets the TIF_MCCK_PENDING bit between the transfer code and the store of current/thread_info the bit is still set for the previous task. And if the previous task has terminated it can get lost. The effect is that a pending CRW is not retrieved until the next machine checks sets TIF_MCCK_PENDING. To fix this reorder __switch_to to first store the task struct and thread-info pointer and then do the transfer of the bit. Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/entry.S | 21 +++++++++++---------- arch/s390/kernel/entry64.S | 21 +++++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 74ee563fe62b..1ae93b573d7d 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -145,22 +145,23 @@ STACK_SIZE = 1 << STACK_SHIFT * gpr2 = prev */ ENTRY(__switch_to) + stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task + st %r15,__THREAD_ksp(%r2) # store kernel stack of prev l %r4,__THREAD_info(%r2) # get thread_info of prev l %r5,__THREAD_info(%r3) # get thread_info of next + lr %r15,%r5 + ahi %r15,STACK_SIZE # end of kernel stack of next + st %r3,__LC_CURRENT # store task struct of next + st %r5,__LC_THREAD_INFO # store thread info of next + st %r15,__LC_KERNEL_STACK # store end of kernel stack + lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 + mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next + l %r15,__THREAD_ksp(%r3) # load kernel stack of next tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending? jz 0f ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next -0: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task - st %r15,__THREAD_ksp(%r2) # store kernel stack of prev - l %r15,__THREAD_ksp(%r3) # load kernel stack of next - lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 - lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task - st %r3,__LC_CURRENT # store task struct of next - mvc __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next - st %r5,__LC_THREAD_INFO # store thread info of next - ahi %r5,STACK_SIZE # end of kernel stack of next - st %r5,__LC_KERNEL_STACK # store end of kernel stack +0: lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task br %r14 __critical_start: diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 02bf601d84bf..229fe1d07749 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -164,22 +164,23 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) * gpr2 = prev */ ENTRY(__switch_to) + stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task + stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev lg %r4,__THREAD_info(%r2) # get thread_info of prev lg %r5,__THREAD_info(%r3) # get thread_info of next + lgr %r15,%r5 + aghi %r15,STACK_SIZE # end of kernel stack of next + stg %r3,__LC_CURRENT # store task struct of next + stg %r5,__LC_THREAD_INFO # store thread info of next + stg %r15,__LC_KERNEL_STACK # store end of kernel stack + lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 + mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next + lg %r15,__THREAD_ksp(%r3) # load kernel stack of next tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending? jz 0f ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next -0: stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task - stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev - lg %r15,__THREAD_ksp(%r3) # load kernel stack of next - lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 - lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task - stg %r3,__LC_CURRENT # store task struct of next - mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next - stg %r5,__LC_THREAD_INFO # store thread info of next - aghi %r5,STACK_SIZE # end of kernel stack of next - stg %r5,__LC_KERNEL_STACK # store end of kernel stack +0: lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task br %r14 __critical_start: -- cgit v1.2.3 From f2962dae0efd81fed06d0687f300725ab063587a Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Tue, 15 May 2012 17:49:12 +0200 Subject: s390/ccwgroup: introduce ccwgroup_create_dev Add a new interface for drivers to create a group device. Via the old interface ccwgroup_create_from_string we would create a virtual device in a way that only the caller of this function would match and bind to. Via the new ccwgroup_create_dev we stop playing games with the driver core and directly set the driver of the new group device. For drivers which have todo additional setup steps (like setting driver_data) provide a new setup driver callback. Reviewed-by: Cornelia Huck Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwgroup.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index f2ea2c56a7e1..f5cfb7925867 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -31,6 +31,7 @@ struct ccwgroup_device { * struct ccwgroup_driver - driver for ccw group devices * @max_slaves: maximum number of slave devices * @driver_id: unique id + * @setup: function called during device creation to setup the device * @probe: function called on probe * @remove: function called on remove * @set_online: function called when device is set online @@ -47,6 +48,7 @@ struct ccwgroup_driver { int max_slaves; unsigned long driver_id; + int (*setup) (struct ccwgroup_device *); int (*probe) (struct ccwgroup_device *); void (*remove) (struct ccwgroup_device *); int (*set_online) (struct ccwgroup_device *); @@ -63,6 +65,9 @@ struct ccwgroup_driver { extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); +int ccwgroup_create_dev(struct device *root, unsigned int creator_id, + struct ccw_driver *cdrv, struct ccwgroup_driver *gdrv, + int num_devices, const char *buf); int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, struct ccw_driver *cdrv, int num_devices, const char *buf); -- cgit v1.2.3 From b7a610f7b4cb95150ee58ea7454ca2ace10634c5 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Tue, 15 May 2012 17:52:07 +0200 Subject: s390/ccwgroup: exploit ccwdev_by_dev_id Instead of finding devices via driver_find_device use the bus_find_device wrapper get_ccwdev_by_dev_id. This allows us to get rid of the ccw_driver argument of ccwgroup_create_dev and thus simplify the interface. Reviewed-by: Cornelia Huck Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwgroup.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index f5cfb7925867..70c3d4d2efe8 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -66,8 +66,8 @@ struct ccwgroup_driver { extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); int ccwgroup_create_dev(struct device *root, unsigned int creator_id, - struct ccw_driver *cdrv, struct ccwgroup_driver *gdrv, - int num_devices, const char *buf); + struct ccwgroup_driver *gdrv, int num_devices, + const char *buf); int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, struct ccw_driver *cdrv, int num_devices, const char *buf); -- cgit v1.2.3 From 9814fdfbecbb030454c46ebab88f8ea9819bc143 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Tue, 15 May 2012 18:03:46 +0200 Subject: s390/ccwgroup: remove ccwgroup_create_from_string Remove the old ccwgroup_create_from_string interface since all drivers have been converted to ccwgroup_create_dev. Also remove now unused members of ccwgroup_driver. Reviewed-by: Cornelia Huck Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwgroup.h | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index 70c3d4d2efe8..f2ef34f6d6e5 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -29,10 +29,7 @@ struct ccwgroup_device { /** * struct ccwgroup_driver - driver for ccw group devices - * @max_slaves: maximum number of slave devices - * @driver_id: unique id * @setup: function called during device creation to setup the device - * @probe: function called on probe * @remove: function called on remove * @set_online: function called when device is set online * @set_offline: function called when device is set offline @@ -45,11 +42,7 @@ struct ccwgroup_device { * @driver: embedded driver structure */ struct ccwgroup_driver { - int max_slaves; - unsigned long driver_id; - int (*setup) (struct ccwgroup_device *); - int (*probe) (struct ccwgroup_device *); void (*remove) (struct ccwgroup_device *); int (*set_online) (struct ccwgroup_device *); int (*set_offline) (struct ccwgroup_device *); @@ -65,12 +58,8 @@ struct ccwgroup_driver { extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); -int ccwgroup_create_dev(struct device *root, unsigned int creator_id, - struct ccwgroup_driver *gdrv, int num_devices, - const char *buf); -int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, - struct ccw_driver *cdrv, int num_devices, - const char *buf); +int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv, + int num_devices, const char *buf); extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); -- cgit v1.2.3