Commit 79811647 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (35 commits)
  [S390] time: remove unused code
  [S390] zcore: Add prefix registers to dump header
  [S390] correct vdso version string
  [S390] add support for compressed kernels
  [S390] Define new s390 ELF note sections in elf.h
  [S390] codepage conversion of kernel parameter line
  [S390] seq_file: convert drivers/s390/
  [S390] add z9-ec/z10 instruction to kernel disassembler
  [S390] dasd: correct offline processing
  [S390] dasd: fix refcounting.
  [S390] dasd: fix online/offline race
  [S390] use kprobes_built_in() in mm/fault code
  [S390] bug: use relative pointers in bug table entries
  [S390] Cleanup struct _lowcore usage and defines.
  [S390] free_initmem: reduce code duplication
  [S390] Replace ENOTSUPP usage with EOPNOTSUPP
  [S390] spinlock: check virtual cpu running status
  [S390] sysinfo: fix SYSIB 3,2,2 structure
  [S390] add MACHINE_IS_LPAR flag
  [S390] qdio: optimize cache line usage of struct qdio_irq
  ...
parents f1dd6ad5 a8d6356c
...@@ -87,6 +87,12 @@ Command line parameters ...@@ -87,6 +87,12 @@ Command line parameters
compatibility, by the device number in hexadecimal (0xabcd or abcd). Device compatibility, by the device number in hexadecimal (0xabcd or abcd). Device
numbers given as 0xabcd will be interpreted as 0.0.abcd. numbers given as 0xabcd will be interpreted as 0.0.abcd.
* /proc/cio_settle
A write request to this file is blocked until all queued cio actions are
handled. This will allow userspace to wait for pending work affecting
device availability after changing cio_ignore or the hardware configuration.
* For some of the information present in the /proc filesystem in 2.4 (namely, * For some of the information present in the /proc filesystem in 2.4 (namely,
/proc/subchannels and /proc/chpids), see driver-model.txt. /proc/subchannels and /proc/chpids), see driver-model.txt.
Information formerly in /proc/irq_count is now in /proc/interrupts. Information formerly in /proc/irq_count is now in /proc/interrupts.
......
...@@ -223,8 +223,8 @@ touched by the driver - it should use the ccwgroup device's driver_data for its ...@@ -223,8 +223,8 @@ touched by the driver - it should use the ccwgroup device's driver_data for its
private data. private data.
To implement a ccwgroup driver, please refer to include/asm/ccwgroup.h. Keep in To implement a ccwgroup driver, please refer to include/asm/ccwgroup.h. Keep in
mind that most drivers will need to implement both a ccwgroup and a ccw driver mind that most drivers will need to implement both a ccwgroup and a ccw
(unless you have a meta ccw driver, like cu3088 for lcs and ctc). driver.
2. Channel paths 2. Channel paths
......
...@@ -54,6 +54,9 @@ config GENERIC_BUG ...@@ -54,6 +54,9 @@ config GENERIC_BUG
depends on BUG depends on BUG
default y default y
config GENERIC_BUG_RELATIVE_POINTERS
def_bool y
config NO_IOMEM config NO_IOMEM
def_bool y def_bool y
...@@ -95,6 +98,9 @@ config S390 ...@@ -95,6 +98,9 @@ config S390
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select INIT_ALL_POSSIBLE select INIT_ALL_POSSIBLE
select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_LZMA
select ARCH_INLINE_SPIN_TRYLOCK select ARCH_INLINE_SPIN_TRYLOCK
select ARCH_INLINE_SPIN_TRYLOCK_BH select ARCH_INLINE_SPIN_TRYLOCK_BH
select ARCH_INLINE_SPIN_LOCK select ARCH_INLINE_SPIN_LOCK
......
...@@ -6,4 +6,17 @@ config TRACE_IRQFLAGS_SUPPORT ...@@ -6,4 +6,17 @@ config TRACE_IRQFLAGS_SUPPORT
source "lib/Kconfig.debug" source "lib/Kconfig.debug"
config DEBUG_STRICT_USER_COPY_CHECKS
bool "Strict user copy size checks"
---help---
Enabling this option turns a certain set of sanity checks for user
copy operations into compile time warnings.
The copy_from_user() etc checks are there to help test if there
are sufficient security checks on the length argument of
the copy operation, by having gcc prove that the argument is
within bounds.
If unsure, or if you run an older (pre 4.4) gcc, say N.
endmenu endmenu
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
# #
ifndef CONFIG_64BIT ifndef CONFIG_64BIT
LD_BFD := elf32-s390
LDFLAGS := -m elf_s390 LDFLAGS := -m elf_s390
KBUILD_CFLAGS += -m31 KBUILD_CFLAGS += -m31
KBUILD_AFLAGS += -m31 KBUILD_AFLAGS += -m31
...@@ -21,6 +22,7 @@ UTS_MACHINE := s390 ...@@ -21,6 +22,7 @@ UTS_MACHINE := s390
STACK_SIZE := 8192 STACK_SIZE := 8192
CHECKFLAGS += -D__s390__ -msize-long CHECKFLAGS += -D__s390__ -msize-long
else else
LD_BFD := elf64-s390
LDFLAGS := -m elf64_s390 LDFLAGS := -m elf64_s390
MODFLAGS += -fpic -D__PIC__ MODFLAGS += -fpic -D__PIC__
KBUILD_CFLAGS += -m64 KBUILD_CFLAGS += -m64
...@@ -30,6 +32,8 @@ STACK_SIZE := 16384 ...@@ -30,6 +32,8 @@ STACK_SIZE := 16384
CHECKFLAGS += -D__s390__ -D__s390x__ CHECKFLAGS += -D__s390__ -D__s390x__
endif endif
export LD_BFD
cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5) cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5)
cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
...@@ -85,7 +89,9 @@ KBUILD_AFLAGS += $(aflags-y) ...@@ -85,7 +89,9 @@ KBUILD_AFLAGS += $(aflags-y)
OBJCOPYFLAGS := -O binary OBJCOPYFLAGS := -O binary
LDFLAGS_vmlinux := -e start LDFLAGS_vmlinux := -e start
head-y := arch/s390/kernel/head.o arch/s390/kernel/init_task.o head-y := arch/s390/kernel/head.o
head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
head-y += arch/s390/kernel/init_task.o
core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \ core-y += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/ arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
...@@ -99,12 +105,12 @@ drivers-$(CONFIG_OPROFILE) += arch/s390/oprofile/ ...@@ -99,12 +105,12 @@ drivers-$(CONFIG_OPROFILE) += arch/s390/oprofile/
boot := arch/s390/boot boot := arch/s390/boot
all: image all: image bzImage
install: vmlinux install: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@ $(Q)$(MAKE) $(build)=$(boot) $@
image: vmlinux image bzImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
zfcpdump: zfcpdump:
...@@ -116,4 +122,5 @@ archclean: ...@@ -116,4 +122,5 @@ archclean:
# Don't use tabs in echo arguments # Don't use tabs in echo arguments
define archhelp define archhelp
echo '* image - Kernel image for IPL ($(boot)/image)' echo '* image - Kernel image for IPL ($(boot)/image)'
echo '* bzImage - Compressed kernel image for IPL ($(boot)/bzImage)'
endef endef
...@@ -9,10 +9,18 @@ COMPILE_VERSION := __linux_compile_version_id__`hostname | \ ...@@ -9,10 +9,18 @@ COMPILE_VERSION := __linux_compile_version_id__`hostname | \
EXTRA_CFLAGS := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I. EXTRA_CFLAGS := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
targets := image targets := image
targets += bzImage
subdir- := compressed
$(obj)/image: vmlinux FORCE $(obj)/image: vmlinux FORCE
$(call if_changed,objcopy) $(call if_changed,objcopy)
$(obj)/bzImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
install: $(CONFIGURE) $(obj)/image install: $(CONFIGURE) $(obj)/image
sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/image \ sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/image \
System.map Kerntypes "$(INSTALL_PATH)" System.map Kerntypes "$(INSTALL_PATH)"
#
# linux/arch/s390/boot/compressed/Makefile
#
# create a compressed vmlinux image from the original vmlinux
#
BITS := $(if $(CONFIG_64BIT),64,31)
targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \
vmlinux.bin.lzma misc.o piggy.o sizes.h head$(BITS).o
KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
KBUILD_CFLAGS += $(cflags-y)
KBUILD_CFLAGS += $(call cc-option,-mpacked-stack)
KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
GCOV_PROFILE := n
OBJECTS := $(addprefix $(objtree)/arch/s390/kernel/, head.o sclp.o ebcdic.o)
OBJECTS += $(obj)/head$(BITS).o $(obj)/misc.o $(obj)/piggy.o
LDFLAGS_vmlinux := --oformat $(LD_BFD) -e startup -T
$(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS)
$(call if_changed,ld)
@:
sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\)$$/\#define SZ\2 0x\1/p'
quiet_cmd_sizes = GEN $@
cmd_sizes = $(NM) $< | sed -n $(sed-sizes) > $@
$(obj)/sizes.h: vmlinux
$(call if_changed,sizes)
AFLAGS_head$(BITS).o += -I$(obj)
$(obj)/head$(BITS).o: $(obj)/sizes.h
CFLAGS_misc.o += -I$(obj)
$(obj)/misc.o: $(obj)/sizes.h
OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
$(obj)/vmlinux.bin: vmlinux
$(call if_changed,objcopy)
vmlinux.bin.all-y := $(obj)/vmlinux.bin
suffix-$(CONFIG_KERNEL_GZIP) := gz
suffix-$(CONFIG_KERNEL_BZIP2) := bz2
suffix-$(CONFIG_KERNEL_LZMA) := lzma
$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y)
$(call if_changed,gzip)
$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y)
$(call if_changed,bzip2)
$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y)
$(call if_changed,lzma)
LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y)
$(call if_changed,ld)
/*
* Startup glue code to uncompress the kernel
*
* Copyright IBM Corp. 2010
*
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <linux/init.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#include "sizes.h"
__HEAD
.globl startup_continue
startup_continue:
basr %r13,0 # get base
.LPG1:
# setup stack
l %r15,.Lstack-.LPG1(%r13)
ahi %r15,-96
l %r1,.Ldecompress-.LPG1(%r13)
basr %r14,%r1
# setup registers for memory mover & branch to target
lr %r4,%r2
l %r2,.Loffset-.LPG1(%r13)
la %r4,0(%r2,%r4)
l %r3,.Lmvsize-.LPG1(%r13)
lr %r5,%r3
# move the memory mover someplace safe
la %r1,0x200
mvc 0(mover_end-mover,%r1),mover-.LPG1(%r13)
# decompress image is started at 0x11000
lr %r6,%r2
br %r1
mover:
mvcle %r2,%r4,0
jo mover
br %r6
mover_end:
.align 8
.Lstack:
.long 0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
.Ldecompress:
.long decompress_kernel
.Loffset:
.long 0x11000
.Lmvsize:
.long SZ__bss_start
/*
* Startup glue code to uncompress the kernel
*
* Copyright IBM Corp. 2010
*
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <linux/init.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#include "sizes.h"
__HEAD
.globl startup_continue
startup_continue:
basr %r13,0 # get base
.LPG1:
# setup stack
lg %r15,.Lstack-.LPG1(%r13)
aghi %r15,-160
brasl %r14,decompress_kernel
# setup registers for memory mover & branch to target
lgr %r4,%r2
lg %r2,.Loffset-.LPG1(%r13)
la %r4,0(%r2,%r4)
lg %r3,.Lmvsize-.LPG1(%r13)
lgr %r5,%r3
# move the memory mover someplace safe
la %r1,0x200
mvc 0(mover_end-mover,%r1),mover-.LPG1(%r13)
# decompress image is started at 0x11000
lgr %r6,%r2
br %r1
mover:
mvcle %r2,%r4,0
jo mover
br %r6
mover_end:
.align 8
.Lstack:
.quad 0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
.Loffset:
.quad 0x11000
.Lmvsize:
.quad SZ__bss_start
/*
* Definitions and wrapper functions for kernel decompressor
*
* Copyright IBM Corp. 2010
*
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/ipl.h>
#include "sizes.h"
/*
* gzip declarations
*/
#define STATIC static
#undef memset
#undef memcpy
#undef memmove
#define memzero(s, n) memset((s), 0, (n))
/* Symbols defined by linker scripts */
extern char input_data[];
extern int input_len;
extern int _text;
extern int _end;
static void error(char *m);
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
#ifdef CONFIG_HAVE_KERNEL_BZIP2
#define HEAP_SIZE 0x400000
#else
#define HEAP_SIZE 0x10000
#endif
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
#ifdef CONFIG_KERNEL_BZIP2
#include "../../../../lib/decompress_bunzip2.c"
#endif
#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif
extern _sclp_print_early(const char *);
int puts(const char *s)
{
_sclp_print_early(s);
return 0;
}
void *memset(void *s, int c, size_t n)
{
char *xs;
if (c == 0)
return __builtin_memset(s, 0, n);
xs = (char *) s;
if (n > 0)
do {
*xs++ = c;
} while (--n > 0);
return s;
}
void *memcpy(void *__dest, __const void *__src, size_t __n)
{
return __builtin_memcpy(__dest, __src, __n);
}
void *memmove(void *__dest, __const void *__src, size_t __n)
{
char *d;
const char *s;
if (__dest <= __src)
return __builtin_memcpy(__dest, __src, __n);
d = __dest + __n;
s = __src + __n;
while (__n--)
*--d = *--s;
return __dest;
}
static void error(char *x)
{
unsigned long long psw = 0x000a0000deadbeefULL;
puts("\n\n");
puts(x);
puts("\n\n -- System halted");
asm volatile("lpsw %0" : : "Q" (psw));
}
/*
* Safe guard the ipl parameter block against a memory area that will be
* overwritten. The validity check for the ipl parameter block is complex
* (see cio_get_iplinfo and ipl_save_parameters) but if the pointer to
* the ipl parameter block intersects with the passed memory area we can
* safely assume that we can read from that memory. In that case just copy
* the memory to IPL_PARMBLOCK_ORIGIN even if there is no ipl parameter
* block.
*/
static void check_ipl_parmblock(void *start, unsigned long size)
{
void *src, *dst;
src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;
if (src + PAGE_SIZE <= start || src >= start + size)
return;
dst = (void *) IPL_PARMBLOCK_ORIGIN;
memmove(dst, src, PAGE_SIZE);
S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
}
unsigned long decompress_kernel(void)
{
unsigned long output_addr;
unsigned char *output;
free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
output = (unsigned char *) ((free_mem_end_ptr + 4095UL) & -4096UL);
check_ipl_parmblock((void *) 0, (unsigned long) output + SZ__bss_start);
#ifdef CONFIG_BLK_DEV_INITRD
/*
* Move the initrd right behind the end of the decompressed
* kernel image.
*/
if (INITRD_START && INITRD_SIZE &&
INITRD_START < (unsigned long) output + SZ__bss_start) {
check_ipl_parmblock(output + SZ__bss_start,
INITRD_START + INITRD_SIZE);
memmove(output + SZ__bss_start,
(void *) INITRD_START, INITRD_SIZE);
INITRD_START = (unsigned long) output + SZ__bss_start;
}
#endif
puts("Uncompressing Linux... ");
decompress(input_data, input_len, NULL, NULL, output, NULL, error);
puts("Ok, booting the kernel.\n");
return (unsigned long) output;
}
#include <asm-generic/vmlinux.lds.h>
#ifdef CONFIG_64BIT
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
OUTPUT_ARCH(s390:64-bit)
#else
OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
OUTPUT_ARCH(s390)
#endif
ENTRY(startup)
SECTIONS
{
/* Be careful parts of head_64.S assume startup_32 is at
* address 0.
*/
. = 0;
.head.text : {
_head = . ;
HEAD_TEXT
_ehead = . ;
}
.rodata.compressed : {
*(.rodata.compressed)
}
.text : {
_text = .; /* Text */
*(.text)
*(.text.*)
_etext = . ;
}
.rodata : {
_rodata = . ;
*(.rodata) /* read-only data */
*(.rodata.*)
_erodata = . ;
}
.data : {
_data = . ;
*(.data)
*(.data.*)
_edata = . ;
}
. = ALIGN(256);
.bss : {
_bss = . ;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(8); /* For convenience during zeroing */
_ebss = .;
}
_end = .;
}
SECTIONS
{
.rodata.compressed : {
input_len = .;
LONG(input_data_end - input_data) input_data = .;
*(.data)
output_len = . - 4;
input_data_end = .;
}
}
...@@ -36,6 +36,13 @@ CONFIG_LOCK_KERNEL=y ...@@ -36,6 +36,13 @@ CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y CONFIG_LOCALVERSION_AUTO=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_LZO is not set
CONFIG_SWAP=y CONFIG_SWAP=y
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y CONFIG_SYSVIPC_SYSCTL=y
......
...@@ -488,7 +488,7 @@ static void *diag204_store(void) ...@@ -488,7 +488,7 @@ static void *diag204_store(void)
static int diag224(void *ptr) static int diag224(void *ptr)
{ {
int rc = -ENOTSUPP; int rc = -EOPNOTSUPP;
asm volatile( asm volatile(
" diag %1,%2,0x224\n" " diag %1,%2,0x224\n"
...@@ -507,7 +507,7 @@ static int diag224_get_name_table(void) ...@@ -507,7 +507,7 @@ static int diag224_get_name_table(void)
return -ENOMEM; return -ENOMEM;
if (diag224(diag224_cpu_names)) { if (diag224(diag224_cpu_names)) {
kfree(diag224_cpu_names); kfree(diag224_cpu_names);
return -ENOTSUPP; return -EOPNOTSUPP;
} }
EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16); EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
return 0; return 0;
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#define ATOMIC_INIT(i) { (i) } #define ATOMIC_INIT(i) { (i) }
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __CS_LOOP(ptr, op_val, op_string) ({ \ #define __CS_LOOP(ptr, op_val, op_string) ({ \
int old_val, new_val; \ int old_val, new_val; \
asm volatile( \ asm volatile( \
...@@ -35,26 +33,6 @@ ...@@ -35,26 +33,6 @@
new_val; \ new_val; \
}) })
#else /* __GNUC__ */
#define __CS_LOOP(ptr, op_val, op_string) ({ \
int old_val, new_val; \
asm volatile( \
" l %0,0(%3)\n" \
"0: lr %1,%0\n" \
op_string " %1,%4\n" \
" cs %0,%1,0(%3)\n" \
" jl 0b" \
: "=&d" (old_val), "=&d" (new_val), \
"=m" (((atomic_t *)(ptr))->counter) \
: "a" (ptr), "d" (op_val), \
"m" (((atomic_t *)(ptr))->counter) \
: "cc", "memory"); \
new_val; \
})
#endif /* __GNUC__ */
static inline int atomic_read(const atomic_t *v) static inline int atomic_read(const atomic_t *v)
{ {
barrier(); barrier();
...@@ -101,19 +79,11 @@ static inline void atomic_set_mask(unsigned long mask, atomic_t *v) ...@@ -101,19 +79,11 @@ static inline void atomic_set_mask(unsigned long mask, atomic_t *v)
static inline int atomic_cmpxchg(atomic_t *v, int old, int new) static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{ {
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
asm volatile( asm volatile(
" cs %0,%2,%1" " cs %0,%2,%1"
: "+d" (old), "=Q" (v->counter) : "+d" (old), "=Q" (v->counter)
: "d" (new), "Q" (v->counter) : "d" (new), "Q" (v->counter)
: "cc", "memory"); : "cc", "memory");
#else /* __GNUC__ */
asm volatile(
" cs %0,%3,0(%2)"
: "+d" (old), "=m" (v->counter)
: "a" (v), "d" (new), "m" (v->counter)
: "cc", "memory");
#endif /* __GNUC__ */
return old; return old;
} }
...@@ -140,8 +110,6 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) ...@@ -140,8 +110,6 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __CSG_LOOP(ptr, op_val, op_string) ({ \ #define __CSG_LOOP(ptr, op_val, op_string) ({ \
long long old_val, new_val; \ long long old_val, new_val; \
asm volatile( \ asm volatile( \
...@@ -157,26 +125,6 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) ...@@ -157,26 +125,6 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
new_val; \ new_val; \
}) })
#else /* __GNUC__ */
#define __CSG_LOOP(ptr, op_val, op_string) ({ \
long long old_val, new_val; \
asm volatile( \
" lg %0,0(%3)\n" \
"0: lgr %1,%0\n" \
op_string " %1,%4\n" \
" csg %0,%1,0(%3)\n" \
" jl 0b" \
: "=&d" (old_val), "=&d" (new_val), \
"=m" (((atomic_t *)(ptr))->counter) \
: "a" (ptr), "d" (op_val), \
"m" (((atomic_t *)(ptr))->counter) \
: "cc", "memory"); \
new_val; \
})
#endif /* __GNUC__ */
static inline long long atomic64_read(const atomic64_t *v) static inline long long atomic64_read(const atomic64_t *v)
{ {
barrier(); barrier();
...@@ -214,19 +162,11 @@ static inline void atomic64_set_mask(unsigned long mask, atomic64_t *v) ...@@ -214,19 +162,11 @@ static inline void atomic64_set_mask(unsigned long mask, atomic64_t *v)
static inline long long atomic64_cmpxchg(atomic64_t *v, static inline long long atomic64_cmpxchg(atomic64_t *v,
long long old, long long new) long long old, long long new)
{ {
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
asm volatile( asm volatile(
" csg %0,%2,%1" " csg %0,%2,%1"
: "+d" (old), "=Q" (v->counter) : "+d" (old), "=Q" (v->counter)
: "d" (new), "Q" (v->counter) : "d" (new), "Q" (v->counter)
: "cc", "memory"); : "cc", "memory");
#else /* __GNUC__ */
asm volatile(
" csg %0,%3,0(%2)"
: "+d" (old), "=m" (v->counter)
: "a" (v), "d" (new), "m" (v->counter)
: "cc", "memory");
#endif /* __GNUC__ */
return old; return old;
} }
...@@ -243,10 +183,8 @@ static inline long long atomic64_read(const atomic64_t *v) ...@@ -243,10 +183,8 @@ static inline long long atomic64_read(const atomic64_t *v)
register_pair rp; register_pair rp;
asm volatile( asm volatile(
" lm %0,%N0,0(%1)" " lm %0,%N0,%1"
: "=&d" (rp) : "=&d" (rp) : "Q" (v->counter) );
: "a" (&v->counter), "m" (v->counter)
);
return rp.pair; return rp.pair;
} }
...@@ -255,10 +193,8 @@ static inline void atomic64_set(atomic64_t *v, long long i) ...@@ -255,10 +193,8 @@ static inline void atomic64_set(atomic64_t *v, long long i)
register_pair rp = {.pair = i}; register_pair rp = {.pair = i};
asm volatile( asm volatile(
" stm %1,%N1,0(%2)" " stm %1,%N1,%0"
: "=m" (v->counter) : "=Q" (v->counter) : "d" (rp) );
: "d" (rp), "a" (&v->counter)
);
} }
static inline long long atomic64_xchg(atomic64_t *v, long long new) static inline long long atomic64_xchg(atomic64_t *v, long long new)
...@@ -267,11 +203,11 @@ static inline long long atomic64_xchg(atomic64_t *v, long long new) ...@@ -267,11 +203,11 @@ static inline long long atomic64_xchg(atomic64_t *v, long long new)
register_pair rp_old; register_pair rp_old;
asm volatile( asm volatile(
" lm %0,%N0,0(%2)\n" " lm %0,%N0,%1\n"
"0: cds %0,%3,0(%2)\n" "0: cds %0,%2,%1\n"
" jl 0b\n" " jl 0b\n"
: "=&d" (rp_old), "+m" (v->counter) : "=&d" (rp_old), "=Q" (v->counter)
: "a" (&v->counter), "d" (rp_new) : "d" (rp_new), "Q" (v->counter)
: "cc"); : "cc");
return rp_old.pair; return rp_old.pair;
} }
...@@ -283,9 +219,9 @@ static inline long long atomic64_cmpxchg(atomic64_t *v, ...@@ -283,9 +219,9 @@ static inline long long atomic64_cmpxchg(atomic64_t *v,
register_pair rp_new = {.pair = new}; register_pair rp_new = {.pair = new};
asm volatile( asm volatile(
" cds %0,%3,0(%2)" " cds %0,%2,%1"
: "+&d" (rp_old), "+m" (v->counter) : "+&d" (rp_old), "=Q" (v->counter)
: "a" (&v->counter), "d" (rp_new) : "d" (rp_new), "Q" (v->counter)
: "cc"); : "cc");
return rp_old.pair; return rp_old.pair;
} }
......
...@@ -71,8 +71,6 @@ extern const char _sb_findmap[]; ...@@ -71,8 +71,6 @@ extern const char _sb_findmap[];
#define __BITOPS_AND "nr" #define __BITOPS_AND "nr"
#define __BITOPS_XOR "xr" #define __BITOPS_XOR "xr"
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \ #define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
asm volatile( \ asm volatile( \
" l %0,%2\n" \ " l %0,%2\n" \
...@@ -85,22 +83,6 @@ extern const char _sb_findmap[]; ...@@ -85,22 +83,6 @@ extern const char _sb_findmap[];
: "d" (__val), "Q" (*(unsigned long *) __addr) \ : "d" (__val), "Q" (*(unsigned long *) __addr) \
: "cc"); : "cc");
#else /* __GNUC__ */
#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
asm volatile( \
" l %0,0(%4)\n" \
"0: lr %1,%0\n" \
__op_string " %1,%3\n" \
" cs %0,%1,0(%4)\n" \
" jl 0b" \
: "=&d" (__old), "=&d" (__new), \
"=m" (*(unsigned long *) __addr) \
: "d" (__val), "a" (__addr), \
"m" (*(unsigned long *) __addr) : "cc");
#endif /* __GNUC__ */
#else /* __s390x__ */ #else /* __s390x__ */
#define __BITOPS_ALIGN 7 #define __BITOPS_ALIGN 7
...@@ -109,8 +91,6 @@ extern const char _sb_findmap[]; ...@@ -109,8 +91,6 @@ extern const char _sb_findmap[];
#define __BITOPS_AND "ngr" #define __BITOPS_AND "ngr"
#define __BITOPS_XOR "xgr" #define __BITOPS_XOR "xgr"
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \ #define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
asm volatile( \ asm volatile( \
" lg %0,%2\n" \ " lg %0,%2\n" \
...@@ -123,23 +103,6 @@ extern const char _sb_findmap[]; ...@@ -123,23 +103,6 @@ extern const char _sb_findmap[];
: "d" (__val), "Q" (*(unsigned long *) __addr) \ : "d" (__val), "Q" (*(unsigned long *) __addr) \
: "cc"); : "cc");
#else /* __GNUC__ */
#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
asm volatile( \
" lg %0,0(%4)\n" \
"0: lgr %1,%0\n" \
__op_string " %1,%3\n" \
" csg %0,%1,0(%4)\n" \
" jl 0b" \
: "=&d" (__old), "=&d" (__new), \
"=m" (*(unsigned long *) __addr) \
: "d" (__val), "a" (__addr), \
"m" (*(unsigned long *) __addr) : "cc");
#endif /* __GNUC__ */
#endif /* __s390x__ */ #endif /* __s390x__ */
#define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE) #define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
...@@ -261,9 +224,8 @@ static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr) ...@@ -261,9 +224,8 @@ static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
asm volatile( asm volatile(
" oc 0(1,%1),0(%2)" " oc %O0(1,%R0),%1"
: "=m" (*(char *) addr) : "a" (addr), : "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
"a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
} }
static inline void static inline void
...@@ -290,9 +252,8 @@ __clear_bit(unsigned long nr, volatile unsigned long *ptr) ...@@ -290,9 +252,8 @@ __clear_bit(unsigned long nr, volatile unsigned long *ptr)
addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
asm volatile( asm volatile(
" nc 0(1,%1),0(%2)" " nc %O0(1,%R0),%1"
: "=m" (*(char *) addr) : "a" (addr), : "=Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc" );
"a" (_ni_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc");
} }
static inline void static inline void
...@@ -318,9 +279,8 @@ static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr) ...@@ -318,9 +279,8 @@ static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
asm volatile( asm volatile(
" xc 0(1,%1),0(%2)" " xc %O0(1,%R0),%1"
: "=m" (*(char *) addr) : "a" (addr), : "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
"a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
} }
static inline void static inline void
...@@ -349,10 +309,9 @@ test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr) ...@@ -349,10 +309,9 @@ test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr; ch = *(unsigned char *) addr;
asm volatile( asm volatile(
" oc 0(1,%1),0(%2)" " oc %O0(1,%R0),%1"
: "=m" (*(char *) addr) : "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7])
: "a" (addr), "a" (_oi_bitmap + (nr & 7)), : "cc", "memory");
"m" (*(char *) addr) : "cc", "memory");
return (ch >> (nr & 7)) & 1; return (ch >> (nr & 7)) & 1;
} }
#define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y) #define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y)
...@@ -369,10 +328,9 @@ test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr) ...@@ -369,10 +328,9 @@ test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr; ch = *(unsigned char *) addr;
asm volatile( asm volatile(
" nc 0(1,%1),0(%2)" " nc %O0(1,%R0),%1"
: "=m" (*(char *) addr) : "=Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7])
: "a" (addr), "a" (_ni_bitmap + (nr & 7)), : "cc", "memory");
"m" (*(char *) addr) : "cc", "memory");
return (ch >> (nr & 7)) & 1; return (ch >> (nr & 7)) & 1;
} }
#define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y) #define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y)
...@@ -389,10 +347,9 @@ test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr) ...@@ -389,10 +347,9 @@ test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr; ch = *(unsigned char *) addr;
asm volatile( asm volatile(
" xc 0(1,%1),0(%2)" " xc %O0(1,%R0),%1"
: "=m" (*(char *) addr) : "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7])
: "a" (addr), "a" (_oi_bitmap + (nr & 7)), : "cc", "memory");
"m" (*(char *) addr) : "cc", "memory");
return (ch >> (nr & 7)) & 1; return (ch >> (nr & 7)) & 1;
} }
#define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y) #define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y)
...@@ -591,11 +548,11 @@ static inline unsigned long __load_ulong_le(const unsigned long *p, ...@@ -591,11 +548,11 @@ static inline unsigned long __load_ulong_le(const unsigned long *p,
p = (unsigned long *)((unsigned long) p + offset); p = (unsigned long *)((unsigned long) p + offset);
#ifndef __s390x__ #ifndef __s390x__
asm volatile( asm volatile(
" ic %0,0(%1)\n" " ic %0,%O1(%R1)\n"
" icm %0,2,1(%1)\n" " icm %0,2,%O1+1(%R1)\n"
" icm %0,4,2(%1)\n" " icm %0,4,%O1+2(%R1)\n"
" icm %0,8,3(%1)" " icm %0,8,%O1+3(%R1)"
: "=&d" (word) : "a" (p), "m" (*p) : "cc"); : "=&d" (word) : "Q" (*p) : "cc");
#else #else
asm volatile( asm volatile(
" lrvg %0,%1" " lrvg %0,%1"
......
...@@ -5,12 +5,6 @@ ...@@ -5,12 +5,6 @@
#ifdef CONFIG_BUG #ifdef CONFIG_BUG
#ifdef CONFIG_64BIT
#define S390_LONG ".quad"
#else
#define S390_LONG ".long"
#endif
#ifdef CONFIG_DEBUG_BUGVERBOSE #ifdef CONFIG_DEBUG_BUGVERBOSE
#define __EMIT_BUG(x) do { \ #define __EMIT_BUG(x) do { \
...@@ -21,7 +15,7 @@ ...@@ -21,7 +15,7 @@
"2: .asciz \""__FILE__"\"\n" \ "2: .asciz \""__FILE__"\"\n" \
".previous\n" \ ".previous\n" \
".section __bug_table,\"a\"\n" \ ".section __bug_table,\"a\"\n" \
"3:\t" S390_LONG "\t1b,2b\n" \ "3: .long 1b-3b,2b-3b\n" \
" .short %0,%1\n" \ " .short %0,%1\n" \
" .org 3b+%2\n" \ " .org 3b+%2\n" \
".previous\n" \ ".previous\n" \
...@@ -37,7 +31,7 @@ ...@@ -37,7 +31,7 @@
"0: j 0b+2\n" \ "0: j 0b+2\n" \
"1:\n" \ "1:\n" \
".section __bug_table,\"a\"\n" \ ".section __bug_table,\"a\"\n" \
"2:\t" S390_LONG "\t1b\n" \ "2: .long 1b-2b\n" \
" .short %0\n" \ " .short %0\n" \
" .org 2b+%1\n" \ " .org 2b+%1\n" \
".previous\n" \ ".previous\n" \
......
...@@ -32,6 +32,7 @@ typedef void (*crw_handler_t)(struct crw *, struct crw *, int); ...@@ -32,6 +32,7 @@ typedef void (*crw_handler_t)(struct crw *, struct crw *, int);
extern int crw_register_handler(int rsc, crw_handler_t handler); extern int crw_register_handler(int rsc, crw_handler_t handler);
extern void crw_unregister_handler(int rsc); extern void crw_unregister_handler(int rsc);
extern void crw_handle_channel_report(void); extern void crw_handle_channel_report(void);
void crw_wait_for_channel_report(void);
#define NR_RSCS 16 #define NR_RSCS 16
......
...@@ -145,11 +145,11 @@ static inline int etr_setr(struct etr_eacr *ctrl) ...@@ -145,11 +145,11 @@ static inline int etr_setr(struct etr_eacr *ctrl)
int rc = -ENOSYS; int rc = -ENOSYS;
asm volatile( asm volatile(
" .insn s,0xb2160000,0(%2)\n" " .insn s,0xb2160000,%1\n"
"0: la %0,0\n" "0: la %0,0\n"
"1:\n" "1:\n"
EX_TABLE(0b,1b) EX_TABLE(0b,1b)
: "+d" (rc) : "m" (*ctrl), "a" (ctrl)); : "+d" (rc) : "Q" (*ctrl));
return rc; return rc;
} }
...@@ -159,11 +159,11 @@ static inline int etr_stetr(struct etr_aib *aib) ...@@ -159,11 +159,11 @@ static inline int etr_stetr(struct etr_aib *aib)
int rc = -ENOSYS; int rc = -ENOSYS;
asm volatile( asm volatile(
" .insn s,0xb2170000,0(%2)\n" " .insn s,0xb2170000,%1\n"
"0: la %0,0\n" "0: la %0,0\n"
"1:\n" "1:\n"
EX_TABLE(0b,1b) EX_TABLE(0b,1b)
: "+d" (rc) : "m" (*aib), "a" (aib)); : "+d" (rc) : "Q" (*aib));
return rc; return rc;
} }
...@@ -174,11 +174,11 @@ static inline int etr_steai(struct etr_aib *aib, unsigned int func) ...@@ -174,11 +174,11 @@ static inline int etr_steai(struct etr_aib *aib, unsigned int func)
int rc = -ENOSYS; int rc = -ENOSYS;
asm volatile( asm volatile(
" .insn s,0xb2b30000,0(%2)\n" " .insn s,0xb2b30000,%1\n"
"0: la %0,0\n" "0: la %0,0\n"
"1:\n" "1:\n"
EX_TABLE(0b,1b) EX_TABLE(0b,1b)
: "+d" (rc) : "m" (*aib), "a" (aib), "d" (reg0)); : "+d" (rc) : "Q" (*aib), "d" (reg0));
return rc; return rc;
} }
......
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
#include <linux/types.h> #include <linux/types.h>
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
/* store then or system mask. */ /* store then or system mask. */
#define __raw_local_irq_stosm(__or) \ #define __raw_local_irq_stosm(__or) \
({ \ ({ \
...@@ -36,40 +34,6 @@ ...@@ -36,40 +34,6 @@
asm volatile("ssm %0" : : "Q" (__mask) : "memory"); \ asm volatile("ssm %0" : : "Q" (__mask) : "memory"); \
}) })
#else /* __GNUC__ */
/* store then or system mask. */
#define __raw_local_irq_stosm(__or) \
({ \
unsigned long __mask; \
asm volatile( \
" stosm 0(%1),%2" \
: "=m" (__mask) \
: "a" (&__mask), "i" (__or) : "memory"); \
__mask; \
})
/* store then and system mask. */
#define __raw_local_irq_stnsm(__and) \
({ \
unsigned long __mask; \
asm volatile( \
" stnsm 0(%1),%2" \
: "=m" (__mask) \
: "a" (&__mask), "i" (__and) : "memory"); \
__mask; \
})
/* set system mask. */
#define __raw_local_irq_ssm(__mask) \
({ \
asm volatile( \
" ssm 0(%0)" \
: : "a" (&__mask), "m" (__mask) : "memory"); \
})
#endif /* __GNUC__ */
/* interrupt control.. */ /* interrupt control.. */
static inline unsigned long raw_local_irq_enable(void) static inline unsigned long raw_local_irq_enable(void)
{ {
......
/* /*
* include/asm-s390/lowcore.h * Copyright IBM Corp. 1999,2010
* * Author(s): Hartmut Penner <hp@de.ibm.com>,
* S390 version * Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Denis Joseph Barrow,
* Author(s): Hartmut Penner (hp@de.ibm.com),
* Martin Schwidefsky (schwidefsky@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
*/ */
#ifndef _ASM_S390_LOWCORE_H #ifndef _ASM_S390_LOWCORE_H
#define _ASM_S390_LOWCORE_H #define _ASM_S390_LOWCORE_H
#define __LC_IPL_PARMBLOCK_PTR 0x0014
#define __LC_EXT_PARAMS 0x0080
#define __LC_CPU_ADDRESS 0x0084
#define __LC_EXT_INT_CODE 0x0086
#define __LC_SVC_ILC 0x0088
#define __LC_SVC_INT_CODE 0x008a
#define __LC_PGM_ILC 0x008c
#define __LC_PGM_INT_CODE 0x008e
#define __LC_PER_ATMID 0x0096
#define __LC_PER_ADDRESS 0x0098
#define __LC_PER_ACCESS_ID 0x00a1
#define __LC_AR_MODE_ID 0x00a3
#define __LC_SUBCHANNEL_ID 0x00b8
#define __LC_SUBCHANNEL_NR 0x00ba
#define __LC_IO_INT_PARM 0x00bc
#define __LC_IO_INT_WORD 0x00c0
#define __LC_STFL_FAC_LIST 0x00c8
#define __LC_MCCK_CODE 0x00e8
#define __LC_DUMP_REIPL 0x0e00
#ifndef __s390x__
#define __LC_EXT_OLD_PSW 0x0018
#define __LC_SVC_OLD_PSW 0x0020
#define __LC_PGM_OLD_PSW 0x0028
#define __LC_MCK_OLD_PSW 0x0030
#define __LC_IO_OLD_PSW 0x0038
#define __LC_EXT_NEW_PSW 0x0058
#define __LC_SVC_NEW_PSW 0x0060
#define __LC_PGM_NEW_PSW 0x0068
#define __LC_MCK_NEW_PSW 0x0070
#define __LC_IO_NEW_PSW 0x0078
#define __LC_SAVE_AREA 0x0200
#define __LC_RETURN_PSW 0x0240
#define __LC_RETURN_MCCK_PSW 0x0248
#define __LC_SYNC_ENTER_TIMER 0x0250
#define __LC_ASYNC_ENTER_TIMER 0x0258
#define __LC_EXIT_TIMER 0x0260
#define __LC_USER_TIMER 0x0268
#define __LC_SYSTEM_TIMER 0x0270
#define __LC_STEAL_TIMER 0x0278
#define __LC_LAST_UPDATE_TIMER 0x0280
#define __LC_LAST_UPDATE_CLOCK 0x0288
#define __LC_CURRENT 0x0290
#define __LC_THREAD_INFO 0x0294
#define __LC_KERNEL_STACK 0x0298
#define __LC_ASYNC_STACK 0x029c
#define __LC_PANIC_STACK 0x02a0
#define __LC_KERNEL_ASCE 0x02a4
#define __LC_USER_ASCE 0x02a8
#define __LC_USER_EXEC_ASCE 0x02ac
#define __LC_CPUID 0x02b0
#define __LC_INT_CLOCK 0x02c8
#define __LC_MACHINE_FLAGS 0x02d8
#define __LC_FTRACE_FUNC 0x02dc
#define __LC_IRB 0x0300
#define __LC_PFAULT_INTPARM 0x0080
#define __LC_CPU_TIMER_SAVE_AREA 0x00d8
#define __LC_CLOCK_COMP_SAVE_AREA 0x00e0
#define __LC_PSW_SAVE_AREA 0x0100
#define __LC_PREFIX_SAVE_AREA 0x0108
#define __LC_AREGS_SAVE_AREA 0x0120
#define __LC_FPREGS_SAVE_AREA 0x0160
#define __LC_GPREGS_SAVE_AREA 0x0180
#define __LC_CREGS_SAVE_AREA 0x01c0
#else /* __s390x__ */
#define __LC_LAST_BREAK 0x0110
#define __LC_EXT_OLD_PSW 0x0130
#define __LC_SVC_OLD_PSW 0x0140
#define __LC_PGM_OLD_PSW 0x0150
#define __LC_MCK_OLD_PSW 0x0160
#define __LC_IO_OLD_PSW 0x0170
#define __LC_RESTART_PSW 0x01a0
#define __LC_EXT_NEW_PSW 0x01b0
#define __LC_SVC_NEW_PSW 0x01c0
#define __LC_PGM_NEW_PSW 0x01d0
#define __LC_MCK_NEW_PSW 0x01e0
#define __LC_IO_NEW_PSW 0x01f0
#define __LC_SAVE_AREA 0x0200
#define __LC_RETURN_PSW 0x0280
#define __LC_RETURN_MCCK_PSW 0x0290
#define __LC_SYNC_ENTER_TIMER 0x02a0
#define __LC_ASYNC_ENTER_TIMER 0x02a8
#define __LC_EXIT_TIMER 0x02b0
#define __LC_USER_TIMER 0x02b8
#define __LC_SYSTEM_TIMER 0x02c0
#define __LC_STEAL_TIMER 0x02c8
#define __LC_LAST_UPDATE_TIMER 0x02d0
#define __LC_LAST_UPDATE_CLOCK 0x02d8
#define __LC_CURRENT 0x02e0
#define __LC_THREAD_INFO 0x02e8
#define __LC_KERNEL_STACK 0x02f0
#define __LC_ASYNC_STACK 0x02f8
#define __LC_PANIC_STACK 0x0300
#define __LC_KERNEL_ASCE 0x0308
#define __LC_USER_ASCE 0x0310
#define __LC_USER_EXEC_ASCE 0x0318
#define __LC_CPUID 0x0320
#define __LC_INT_CLOCK 0x0340
#define __LC_VDSO_PER_CPU 0x0350
#define __LC_MACHINE_FLAGS 0x0358
#define __LC_FTRACE_FUNC 0x0360
#define __LC_IRB 0x0380
#define __LC_PASTE 0x03c0
#define __LC_PFAULT_INTPARM 0x11b8
#define __LC_FPREGS_SAVE_AREA 0x1200
#define __LC_GPREGS_SAVE_AREA 0x1280
#define __LC_PSW_SAVE_AREA 0x1300
#define __LC_PREFIX_SAVE_AREA 0x1318
#define __LC_FP_CREG_SAVE_AREA 0x131c
#define __LC_TODREG_SAVE_AREA 0x1324
#define __LC_CPU_TIMER_SAVE_AREA 0x1328
#define __LC_CLOCK_COMP_SAVE_AREA 0x1331
#define __LC_AREGS_SAVE_AREA 0x1340
#define __LC_CREGS_SAVE_AREA 0x1380
#endif /* __s390x__ */
#ifndef __ASSEMBLY__
#include <asm/cpu.h>
#include <asm/ptrace.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/ptrace.h>
#include <asm/cpu.h>
void restart_int_handler(void); void restart_int_handler(void);
void ext_int_handler(void); void ext_int_handler(void);
...@@ -144,7 +19,12 @@ void pgm_check_handler(void); ...@@ -144,7 +19,12 @@ void pgm_check_handler(void);
void mcck_int_handler(void); void mcck_int_handler(void);
void io_int_handler(void); void io_int_handler(void);
struct save_area_s390 { #ifdef CONFIG_32BIT
#define LC_ORDER 0
#define LC_PAGES 1
struct save_area {
u32 ext_save; u32 ext_save;
u64 timer; u64 timer;
u64 clk_cmp; u64 clk_cmp;
...@@ -156,54 +36,13 @@ struct save_area_s390 { ...@@ -156,54 +36,13 @@ struct save_area_s390 {
u64 fp_regs[4]; u64 fp_regs[4];
u32 gp_regs[16]; u32 gp_regs[16];
u32 ctrl_regs[16]; u32 ctrl_regs[16];
} __attribute__((packed)); } __packed;
struct save_area_s390x { struct _lowcore {
u64 fp_regs[16];
u64 gp_regs[16];
u8 psw[16];
u8 pad1[8];
u32 pref_reg;
u32 fp_ctrl_reg;
u8 pad2[4];
u32 tod_reg;
u64 timer;
u64 clk_cmp;
u8 pad3[8];
u32 acc_regs[16];
u64 ctrl_regs[16];
} __attribute__((packed));
union save_area {
struct save_area_s390 s390;
struct save_area_s390x s390x;
};
#define SAVE_AREA_BASE_S390 0xd4
#define SAVE_AREA_BASE_S390X 0x1200
#ifndef __s390x__
#define SAVE_AREA_SIZE sizeof(struct save_area_s390)
#define SAVE_AREA_BASE SAVE_AREA_BASE_S390
#else
#define SAVE_AREA_SIZE sizeof(struct save_area_s390x)
#define SAVE_AREA_BASE SAVE_AREA_BASE_S390X
#endif
#ifndef __s390x__
#define LC_ORDER 0
#else
#define LC_ORDER 1
#endif
#define LC_PAGES (1UL << LC_ORDER)
struct _lowcore
{
#ifndef __s390x__
/* 0x0000 - 0x01ff: defined by architecture */
psw_t restart_psw; /* 0x0000 */ psw_t restart_psw; /* 0x0000 */
__u32 ccw2[4]; /* 0x0008 */ psw_t restart_old_psw; /* 0x0008 */
__u8 pad_0x0010[0x0014-0x0010]; /* 0x0010 */
__u32 ipl_parmblock_ptr; /* 0x0014 */
psw_t external_old_psw; /* 0x0018 */ psw_t external_old_psw; /* 0x0018 */
psw_t svc_old_psw; /* 0x0020 */ psw_t svc_old_psw; /* 0x0020 */
psw_t program_old_psw; /* 0x0028 */ psw_t program_old_psw; /* 0x0028 */
...@@ -229,7 +68,9 @@ struct _lowcore ...@@ -229,7 +68,9 @@ struct _lowcore
__u32 monitor_code; /* 0x009c */ __u32 monitor_code; /* 0x009c */
__u8 exc_access_id; /* 0x00a0 */ __u8 exc_access_id; /* 0x00a0 */
__u8 per_access_id; /* 0x00a1 */ __u8 per_access_id; /* 0x00a1 */
__u8 pad_0x00a2[0x00b8-0x00a2]; /* 0x00a2 */ __u8 op_access_id; /* 0x00a2 */
__u8 ar_access_id; /* 0x00a3 */
__u8 pad_0x00a4[0x00b8-0x00a4]; /* 0x00a4 */
__u16 subchannel_id; /* 0x00b8 */ __u16 subchannel_id; /* 0x00b8 */
__u16 subchannel_nr; /* 0x00ba */ __u16 subchannel_nr; /* 0x00ba */
__u32 io_int_parm; /* 0x00bc */ __u32 io_int_parm; /* 0x00bc */
...@@ -245,8 +86,9 @@ struct _lowcore ...@@ -245,8 +86,9 @@ struct _lowcore
__u32 external_damage_code; /* 0x00f4 */ __u32 external_damage_code; /* 0x00f4 */
__u32 failing_storage_address; /* 0x00f8 */ __u32 failing_storage_address; /* 0x00f8 */
__u8 pad_0x00fc[0x0100-0x00fc]; /* 0x00fc */ __u8 pad_0x00fc[0x0100-0x00fc]; /* 0x00fc */
__u32 st_status_fixed_logout[4]; /* 0x0100 */ psw_t psw_save_area; /* 0x0100 */
__u8 pad_0x0110[0x0120-0x0110]; /* 0x0110 */ __u32 prefixreg_save_area; /* 0x0108 */
__u8 pad_0x010c[0x0120-0x010c]; /* 0x010c */
/* CPU register save area: defined by architecture */ /* CPU register save area: defined by architecture */
__u32 access_regs_save_area[16]; /* 0x0120 */ __u32 access_regs_save_area[16]; /* 0x0120 */
...@@ -310,10 +152,32 @@ struct _lowcore ...@@ -310,10 +152,32 @@ struct _lowcore
/* Align to the top 1k of prefix area */ /* Align to the top 1k of prefix area */
__u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */
#else /* !__s390x__ */ } __packed;
/* 0x0000 - 0x01ff: defined by architecture */
__u32 ccw1[2]; /* 0x0000 */ #else /* CONFIG_32BIT */
__u32 ccw2[4]; /* 0x0008 */
#define LC_ORDER 1
#define LC_PAGES 2
struct save_area {
u64 fp_regs[16];
u64 gp_regs[16];
u8 psw[16];
u8 pad1[8];
u32 pref_reg;
u32 fp_ctrl_reg;
u8 pad2[4];
u32 tod_reg;
u64 timer;
u64 clk_cmp;
u8 pad3[8];
u32 acc_regs[16];
u64 ctrl_regs[16];
} __packed;
struct _lowcore {
__u8 pad_0x0000[0x0014-0x0000]; /* 0x0000 */
__u32 ipl_parmblock_ptr; /* 0x0014 */
__u8 pad_0x0018[0x0080-0x0018]; /* 0x0018 */ __u8 pad_0x0018[0x0080-0x0018]; /* 0x0018 */
__u32 ext_params; /* 0x0080 */ __u32 ext_params; /* 0x0080 */
__u16 cpu_addr; /* 0x0084 */ __u16 cpu_addr; /* 0x0084 */
...@@ -344,7 +208,9 @@ struct _lowcore ...@@ -344,7 +208,9 @@ struct _lowcore
__u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */
__u32 external_damage_code; /* 0x00f4 */ __u32 external_damage_code; /* 0x00f4 */
addr_t failing_storage_address; /* 0x00f8 */ addr_t failing_storage_address; /* 0x00f8 */
__u8 pad_0x0100[0x0120-0x0100]; /* 0x0100 */ __u8 pad_0x0100[0x0110-0x0100]; /* 0x0100 */
__u64 breaking_event_addr; /* 0x0110 */
__u8 pad_0x0118[0x0120-0x0118]; /* 0x0118 */
psw_t restart_old_psw; /* 0x0120 */ psw_t restart_old_psw; /* 0x0120 */
psw_t external_old_psw; /* 0x0130 */ psw_t external_old_psw; /* 0x0130 */
psw_t svc_old_psw; /* 0x0140 */ psw_t svc_old_psw; /* 0x0140 */
...@@ -425,7 +291,7 @@ struct _lowcore ...@@ -425,7 +291,7 @@ struct _lowcore
/* CPU register save area: defined by architecture */ /* CPU register save area: defined by architecture */
__u64 floating_pt_save_area[16]; /* 0x1200 */ __u64 floating_pt_save_area[16]; /* 0x1200 */
__u64 gpregs_save_area[16]; /* 0x1280 */ __u64 gpregs_save_area[16]; /* 0x1280 */
__u32 st_status_fixed_logout[4]; /* 0x1300 */ psw_t psw_save_area; /* 0x1300 */
__u8 pad_0x1310[0x1318-0x1310]; /* 0x1310 */ __u8 pad_0x1310[0x1318-0x1310]; /* 0x1310 */
__u32 prefixreg_save_area; /* 0x1318 */ __u32 prefixreg_save_area; /* 0x1318 */
__u32 fpt_creg_save_area; /* 0x131c */ __u32 fpt_creg_save_area; /* 0x131c */
...@@ -439,10 +305,12 @@ struct _lowcore ...@@ -439,10 +305,12 @@ struct _lowcore
/* align to the top of the prefix area */ /* align to the top of the prefix area */
__u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */ __u8 pad_0x1400[0x2000-0x1400]; /* 0x1400 */
#endif /* !__s390x__ */ } __packed;
} __attribute__((packed)); /* End structure*/
#endif /* CONFIG_32BIT */
#define S390_lowcore (*((struct _lowcore *) 0)) #define S390_lowcore (*((struct _lowcore *) 0))
extern struct _lowcore *lowcore_ptr[]; extern struct _lowcore *lowcore_ptr[];
static inline void set_prefix(__u32 address) static inline void set_prefix(__u32 address)
...@@ -458,6 +326,4 @@ static inline __u32 store_prefix(void) ...@@ -458,6 +326,4 @@ static inline __u32 store_prefix(void)
return address; return address;
} }
#endif #endif /* _ASM_S390_LOWCORE_H */
#endif
...@@ -107,9 +107,6 @@ typedef pte_t *pgtable_t; ...@@ -107,9 +107,6 @@ typedef pte_t *pgtable_t;
#define __pgd(x) ((pgd_t) { (x) } ) #define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } ) #define __pgprot(x) ((pgprot_t) { (x) } )
/* default storage key used for all pages */
extern unsigned int default_storage_key;
static inline void static inline void
page_set_storage_key(unsigned long addr, unsigned int skey) page_set_storage_key(unsigned long addr, unsigned int skey)
{ {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
static inline void get_cpu_id(struct cpuid *ptr) static inline void get_cpu_id(struct cpuid *ptr)
{ {
asm volatile("stidp 0(%1)" : "=m" (*ptr) : "a" (ptr)); asm volatile("stidp %0" : "=Q" (*ptr));
} }
extern void s390_adjust_jiffies(void); extern void s390_adjust_jiffies(void);
...@@ -184,9 +184,9 @@ static inline void psw_set_key(unsigned int key) ...@@ -184,9 +184,9 @@ static inline void psw_set_key(unsigned int key)
static inline void __load_psw(psw_t psw) static inline void __load_psw(psw_t psw)
{ {
#ifndef __s390x__ #ifndef __s390x__
asm volatile("lpsw 0(%0)" : : "a" (&psw), "m" (psw) : "cc"); asm volatile("lpsw %0" : : "Q" (psw) : "cc");
#else #else
asm volatile("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc"); asm volatile("lpswe %0" : : "Q" (psw) : "cc");
#endif #endif
} }
...@@ -206,17 +206,17 @@ static inline void __load_psw_mask (unsigned long mask) ...@@ -206,17 +206,17 @@ static inline void __load_psw_mask (unsigned long mask)
asm volatile( asm volatile(
" basr %0,0\n" " basr %0,0\n"
"0: ahi %0,1f-0b\n" "0: ahi %0,1f-0b\n"
" st %0,4(%1)\n" " st %0,%O1+4(%R1)\n"
" lpsw 0(%1)\n" " lpsw %1\n"
"1:" "1:"
: "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc"); : "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
#else /* __s390x__ */ #else /* __s390x__ */
asm volatile( asm volatile(
" larl %0,1f\n" " larl %0,1f\n"
" stg %0,8(%1)\n" " stg %0,%O1+8(%R1)\n"
" lpswe 0(%1)\n" " lpswe %1\n"
"1:" "1:"
: "=&d" (addr) : "a" (&psw), "m" (psw) : "memory", "cc"); : "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc");
#endif /* __s390x__ */ #endif /* __s390x__ */
} }
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#define QDIO_MAX_QUEUES_PER_IRQ 32 /* only use 4 queues to save some cachelines */
#define QDIO_MAX_QUEUES_PER_IRQ 4
#define QDIO_MAX_BUFFERS_PER_Q 128 #define QDIO_MAX_BUFFERS_PER_Q 128
#define QDIO_MAX_BUFFERS_MASK (QDIO_MAX_BUFFERS_PER_Q - 1) #define QDIO_MAX_BUFFERS_MASK (QDIO_MAX_BUFFERS_PER_Q - 1)
#define QDIO_MAX_ELEMENTS_PER_BUFFER 16 #define QDIO_MAX_ELEMENTS_PER_BUFFER 16
......
...@@ -124,21 +124,21 @@ static inline void __down_read(struct rw_semaphore *sem) ...@@ -124,21 +124,21 @@ static inline void __down_read(struct rw_semaphore *sem)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ahi %1,%5\n" " ahi %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" aghi %1,%5\n" " aghi %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), : "Q" (sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
"i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory"); : "cc", "memory");
if (old < 0) if (old < 0)
rwsem_down_read_failed(sem); rwsem_down_read_failed(sem);
} }
...@@ -152,25 +152,25 @@ static inline int __down_read_trylock(struct rw_semaphore *sem) ...@@ -152,25 +152,25 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: ltr %1,%0\n" "0: ltr %1,%0\n"
" jm 1f\n" " jm 1f\n"
" ahi %1,%5\n" " ahi %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b\n" " jl 0b\n"
"1:" "1:"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: ltgr %1,%0\n" "0: ltgr %1,%0\n"
" jm 1f\n" " jm 1f\n"
" aghi %1,%5\n" " aghi %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b\n" " jl 0b\n"
"1:" "1:"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), : "Q" (sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
"i" (RWSEM_ACTIVE_READ_BIAS) : "cc", "memory"); : "cc", "memory");
return old >= 0 ? 1 : 0; return old >= 0 ? 1 : 0;
} }
...@@ -184,20 +184,20 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) ...@@ -184,20 +184,20 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
tmp = RWSEM_ACTIVE_WRITE_BIAS; tmp = RWSEM_ACTIVE_WRITE_BIAS;
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" a %1,%5\n" " a %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" ag %1,%5\n" " ag %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), "m" (tmp) : "Q" (sem->count), "m" (tmp)
: "cc", "memory"); : "cc", "memory");
if (old != 0) if (old != 0)
rwsem_down_write_failed(sem); rwsem_down_write_failed(sem);
...@@ -217,22 +217,22 @@ static inline int __down_write_trylock(struct rw_semaphore *sem) ...@@ -217,22 +217,22 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%2)\n" " l %0,%1\n"
"0: ltr %0,%0\n" "0: ltr %0,%0\n"
" jnz 1f\n" " jnz 1f\n"
" cs %0,%4,0(%2)\n" " cs %0,%3,%1\n"
" jl 0b\n" " jl 0b\n"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%2)\n" " lg %0,%1\n"
"0: ltgr %0,%0\n" "0: ltgr %0,%0\n"
" jnz 1f\n" " jnz 1f\n"
" csg %0,%4,0(%2)\n" " csg %0,%3,%1\n"
" jl 0b\n" " jl 0b\n"
#endif /* __s390x__ */ #endif /* __s390x__ */
"1:" "1:"
: "=&d" (old), "=m" (sem->count) : "=&d" (old), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), : "Q" (sem->count), "d" (RWSEM_ACTIVE_WRITE_BIAS)
"d" (RWSEM_ACTIVE_WRITE_BIAS) : "cc", "memory"); : "cc", "memory");
return (old == RWSEM_UNLOCKED_VALUE) ? 1 : 0; return (old == RWSEM_UNLOCKED_VALUE) ? 1 : 0;
} }
...@@ -245,21 +245,20 @@ static inline void __up_read(struct rw_semaphore *sem) ...@@ -245,21 +245,20 @@ static inline void __up_read(struct rw_semaphore *sem)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ahi %1,%5\n" " ahi %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" aghi %1,%5\n" " aghi %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), : "Q" (sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS)
"i" (-RWSEM_ACTIVE_READ_BIAS)
: "cc", "memory"); : "cc", "memory");
if (new < 0) if (new < 0)
if ((new & RWSEM_ACTIVE_MASK) == 0) if ((new & RWSEM_ACTIVE_MASK) == 0)
...@@ -276,20 +275,20 @@ static inline void __up_write(struct rw_semaphore *sem) ...@@ -276,20 +275,20 @@ static inline void __up_write(struct rw_semaphore *sem)
tmp = -RWSEM_ACTIVE_WRITE_BIAS; tmp = -RWSEM_ACTIVE_WRITE_BIAS;
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" a %1,%5\n" " a %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" ag %1,%5\n" " ag %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), "m" (tmp) : "Q" (sem->count), "m" (tmp)
: "cc", "memory"); : "cc", "memory");
if (new < 0) if (new < 0)
if ((new & RWSEM_ACTIVE_MASK) == 0) if ((new & RWSEM_ACTIVE_MASK) == 0)
...@@ -306,20 +305,20 @@ static inline void __downgrade_write(struct rw_semaphore *sem) ...@@ -306,20 +305,20 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
tmp = -RWSEM_WAITING_BIAS; tmp = -RWSEM_WAITING_BIAS;
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" a %1,%5\n" " a %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" ag %1,%5\n" " ag %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), "m" (tmp) : "Q" (sem->count), "m" (tmp)
: "cc", "memory"); : "cc", "memory");
if (new > 1) if (new > 1)
rwsem_downgrade_wake(sem); rwsem_downgrade_wake(sem);
...@@ -334,20 +333,20 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) ...@@ -334,20 +333,20 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ar %1,%5\n" " ar %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" agr %1,%5\n" " agr %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), "d" (delta) : "Q" (sem->count), "d" (delta)
: "cc", "memory"); : "cc", "memory");
} }
...@@ -360,20 +359,20 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) ...@@ -360,20 +359,20 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" l %0,0(%3)\n" " l %0,%2\n"
"0: lr %1,%0\n" "0: lr %1,%0\n"
" ar %1,%5\n" " ar %1,%4\n"
" cs %0,%1,0(%3)\n" " cs %0,%1,%2\n"
" jl 0b" " jl 0b"
#else /* __s390x__ */ #else /* __s390x__ */
" lg %0,0(%3)\n" " lg %0,%2\n"
"0: lgr %1,%0\n" "0: lgr %1,%0\n"
" agr %1,%5\n" " agr %1,%4\n"
" csg %0,%1,0(%3)\n" " csg %0,%1,%2\n"
" jl 0b" " jl 0b"
#endif /* __s390x__ */ #endif /* __s390x__ */
: "=&d" (old), "=&d" (new), "=m" (sem->count) : "=&d" (old), "=&d" (new), "=Q" (sem->count)
: "a" (&sem->count), "m" (sem->count), "d" (delta) : "Q" (sem->count), "d" (delta)
: "cc", "memory"); : "cc", "memory");
return new; return new;
} }
......
...@@ -14,14 +14,14 @@ ...@@ -14,14 +14,14 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/lowcore.h>
#include <asm/types.h>
#define PARMAREA 0x10400 #define PARMAREA 0x10400
#define MEMORY_CHUNKS 256 #define MEMORY_CHUNKS 256
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/lowcore.h>
#include <asm/types.h>
#ifndef __s390x__ #ifndef __s390x__
#define IPL_DEVICE (*(unsigned long *) (0x10404)) #define IPL_DEVICE (*(unsigned long *) (0x10404))
#define INITRD_START (*(unsigned long *) (0x1040C)) #define INITRD_START (*(unsigned long *) (0x1040C))
...@@ -71,9 +71,12 @@ extern unsigned int user_mode; ...@@ -71,9 +71,12 @@ extern unsigned int user_mode;
#define MACHINE_FLAG_KVM (1UL << 9) #define MACHINE_FLAG_KVM (1UL << 9)
#define MACHINE_FLAG_HPAGE (1UL << 10) #define MACHINE_FLAG_HPAGE (1UL << 10)
#define MACHINE_FLAG_PFMF (1UL << 11) #define MACHINE_FLAG_PFMF (1UL << 11)
#define MACHINE_FLAG_LPAR (1UL << 12)
#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
#define MACHINE_IS_LPAR (S390_lowcore.machine_flags & MACHINE_FLAG_LPAR)
#define MACHINE_HAS_DIAG9C (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C) #define MACHINE_HAS_DIAG9C (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C)
#ifndef __s390x__ #ifndef __s390x__
......
/* /*
* include/asm-s390/sigp.h * Routines and structures for signalling other processors.
* *
* S390 version * Copyright IBM Corp. 1999,2010
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Denis Joseph Barrow,
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), * Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Martin Schwidefsky (schwidefsky@de.ibm.com) * Heiko Carstens <heiko.carstens@de.ibm.com>,
* Heiko Carstens (heiko.carstens@de.ibm.com)
*
* sigp.h by D.J. Barrow (c) IBM 1999
* contains routines / structures for signalling other S/390 processors in an
* SMP configuration.
*/ */
#ifndef __SIGP__ #ifndef __ASM_SIGP_H
#define __SIGP__ #define __ASM_SIGP_H
#include <asm/system.h> #include <asm/system.h>
/* get real cpu address from logical cpu number */ /* Get real cpu address from logical cpu number. */
extern int __cpu_logical_map[]; extern unsigned short __cpu_logical_map[];
static inline int cpu_logical_map(int cpu) static inline int cpu_logical_map(int cpu)
{ {
...@@ -29,107 +24,108 @@ static inline int cpu_logical_map(int cpu) ...@@ -29,107 +24,108 @@ static inline int cpu_logical_map(int cpu)
#endif #endif
} }
typedef enum enum {
{ sigp_sense = 1,
sigp_unassigned=0x0, sigp_external_call = 2,
sigp_sense, sigp_emergency_signal = 3,
sigp_external_call, sigp_start = 4,
sigp_emergency_signal, sigp_stop = 5,
sigp_start, sigp_restart = 6,
sigp_stop, sigp_stop_and_store_status = 9,
sigp_restart, sigp_initial_cpu_reset = 11,
sigp_unassigned1, sigp_cpu_reset = 12,
sigp_unassigned2, sigp_set_prefix = 13,
sigp_stop_and_store_status, sigp_store_status_at_address = 14,
sigp_unassigned3, sigp_store_extended_status_at_address = 15,
sigp_initial_cpu_reset, sigp_set_architecture = 18,
sigp_cpu_reset, sigp_conditional_emergency_signal = 19,
sigp_set_prefix, sigp_sense_running = 21,
sigp_store_status_at_address, };
sigp_store_extended_status_at_address
} sigp_order_code; enum {
sigp_order_code_accepted = 0,
typedef __u32 sigp_status_word; sigp_status_stored = 1,
sigp_busy = 2,
typedef enum sigp_not_operational = 3,
{ };
sigp_order_code_accepted=0,
sigp_status_stored,
sigp_busy,
sigp_not_operational
} sigp_ccode;
/* /*
* Definitions for the external call * Definitions for external call.
*/ */
enum {
/* 'Bit' signals, asynchronous */ ec_schedule = 0,
typedef enum
{
ec_schedule=0,
ec_call_function, ec_call_function,
ec_call_function_single, ec_call_function_single,
ec_bit_last };
} ec_bit_sig;
/* /*
* Signal processor * Signal processor.
*/ */
static inline sigp_ccode static inline int raw_sigp(u16 cpu, int order)
signal_processor(__u16 cpu_addr, sigp_order_code order_code)
{ {
register unsigned long reg1 asm ("1") = 0; register unsigned long reg1 asm ("1") = 0;
sigp_ccode ccode; int ccode;
asm volatile( asm volatile(
" sigp %1,%2,0(%3)\n" " sigp %1,%2,0(%3)\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
: "=d" (ccode) : "=d" (ccode)
: "d" (reg1), "d" (cpu_logical_map(cpu_addr)), : "d" (reg1), "d" (cpu),
"a" (order_code) : "cc" , "memory"); "a" (order) : "cc" , "memory");
return ccode; return ccode;
} }
/* /*
* Signal processor with parameter * Signal processor with parameter.
*/ */
static inline sigp_ccode static inline int raw_sigp_p(u32 parameter, u16 cpu, int order)
signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code)
{ {
register unsigned int reg1 asm ("1") = parameter; register unsigned int reg1 asm ("1") = parameter;
sigp_ccode ccode; int ccode;
asm volatile( asm volatile(
" sigp %1,%2,0(%3)\n" " sigp %1,%2,0(%3)\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
: "=d" (ccode) : "=d" (ccode)
: "d" (reg1), "d" (cpu_logical_map(cpu_addr)), : "d" (reg1), "d" (cpu),
"a" (order_code) : "cc" , "memory"); "a" (order) : "cc" , "memory");
return ccode; return ccode;
} }
/* /*
* Signal processor with parameter and return status * Signal processor with parameter and return status.
*/ */
static inline sigp_ccode static inline int raw_sigp_ps(u32 *status, u32 parm, u16 cpu, int order)
signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr,
sigp_order_code order_code)
{ {
register unsigned int reg1 asm ("1") = parameter; register unsigned int reg1 asm ("1") = parm;
sigp_ccode ccode; int ccode;
asm volatile( asm volatile(
" sigp %1,%2,0(%3)\n" " sigp %1,%2,0(%3)\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
: "=d" (ccode), "+d" (reg1) : "=d" (ccode), "+d" (reg1)
: "d" (cpu_logical_map(cpu_addr)), "a" (order_code) : "d" (cpu), "a" (order)
: "cc" , "memory"); : "cc" , "memory");
*statusptr = reg1; *status = reg1;
return ccode; return ccode;
} }
#endif /* __SIGP__ */ static inline int sigp(int cpu, int order)
{
return raw_sigp(cpu_logical_map(cpu), order);
}
static inline int sigp_p(u32 parameter, int cpu, int order)
{
return raw_sigp_p(parameter, cpu_logical_map(cpu), order);
}
static inline int sigp_ps(u32 *status, u32 parm, int cpu, int order)
{
return raw_sigp_ps(status, parm, cpu_logical_map(cpu), order);
}
#endif /* __ASM_SIGP_H */
...@@ -29,7 +29,43 @@ extern int smp_cpu_polarization[]; ...@@ -29,7 +29,43 @@ extern int smp_cpu_polarization[];
extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
extern union save_area *zfcpdump_save_areas[NR_CPUS + 1]; extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *);
extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp,
int from, int to);
extern void smp_restart_cpu(void);
/*
* returns 1 if (virtual) cpu is scheduled
* returns 0 otherwise
*/
static inline int smp_vcpu_scheduled(int cpu)
{
u32 status;
switch (sigp_ps(&status, 0, cpu, sigp_sense_running)) {
case sigp_status_stored:
/* Check for running status */
if (status & 0x400)
return 0;
break;
case sigp_not_operational:
return 0;
default:
break;
}
return 1;
}
#else /* CONFIG_SMP */
static inline void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
{
func(data);
}
#define smp_vcpu_scheduled (1)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
......
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include <linux/smp.h> #include <linux/smp.h>
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
static inline int static inline int
_raw_compare_and_swap(volatile unsigned int *lock, _raw_compare_and_swap(volatile unsigned int *lock,
unsigned int old, unsigned int new) unsigned int old, unsigned int new)
...@@ -27,22 +25,6 @@ _raw_compare_and_swap(volatile unsigned int *lock, ...@@ -27,22 +25,6 @@ _raw_compare_and_swap(volatile unsigned int *lock,
return old; return old;
} }
#else /* __GNUC__ */
static inline int
_raw_compare_and_swap(volatile unsigned int *lock,
unsigned int old, unsigned int new)
{
asm volatile(
" cs %0,%3,0(%4)"
: "=d" (old), "=m" (*lock)
: "0" (old), "d" (new), "a" (lock), "m" (*lock)
: "cc", "memory" );
return old;
}
#endif /* __GNUC__ */
/* /*
* Simple spin lock operations. There are two variants, one clears IRQ's * Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not. * on the local processor, one does not.
......
...@@ -47,11 +47,11 @@ static inline __u32 __arch_swab32p(const __u32 *x) ...@@ -47,11 +47,11 @@ static inline __u32 __arch_swab32p(const __u32 *x)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" icm %0,8,3(%1)\n" " icm %0,8,%O1+3(%R1)\n"
" icm %0,4,2(%1)\n" " icm %0,4,%O1+2(%R1)\n"
" icm %0,2,1(%1)\n" " icm %0,2,%O1+1(%R1)\n"
" ic %0,0(%1)" " ic %0,%1"
: "=&d" (result) : "a" (x), "m" (*x) : "cc"); : "=&d" (result) : "Q" (*x) : "cc");
#else /* __s390x__ */ #else /* __s390x__ */
" lrv %0,%1" " lrv %0,%1"
: "=d" (result) : "m" (*x)); : "=d" (result) : "m" (*x));
...@@ -77,9 +77,9 @@ static inline __u16 __arch_swab16p(const __u16 *x) ...@@ -77,9 +77,9 @@ static inline __u16 __arch_swab16p(const __u16 *x)
asm volatile( asm volatile(
#ifndef __s390x__ #ifndef __s390x__
" icm %0,2,1(%1)\n" " icm %0,2,%O+1(%R1)\n"
" ic %0,0(%1)\n" " ic %0,%1\n"
: "=&d" (result) : "a" (x), "m" (*x) : "cc"); : "=&d" (result) : "Q" (*x) : "cc");
#else /* __s390x__ */ #else /* __s390x__ */
" lrvh %0,%1" " lrvh %0,%1"
: "=d" (result) : "m" (*x)); : "=d" (result) : "m" (*x));
......
...@@ -87,7 +87,8 @@ struct sysinfo_2_2_2 { ...@@ -87,7 +87,8 @@ struct sysinfo_2_2_2 {
struct sysinfo_3_2_2 { struct sysinfo_3_2_2 {
char reserved_0[31]; char reserved_0[31];
unsigned char count; unsigned char :4;
unsigned char count:4;
struct { struct {
char reserved_0[4]; char reserved_0[4];
unsigned short cpus_total; unsigned short cpus_total;
......
...@@ -24,65 +24,65 @@ extern struct task_struct *__switch_to(void *, void *); ...@@ -24,65 +24,65 @@ extern struct task_struct *__switch_to(void *, void *);
static inline void save_fp_regs(s390_fp_regs *fpregs) static inline void save_fp_regs(s390_fp_regs *fpregs)
{ {
asm volatile( asm volatile(
" std 0,8(%1)\n" " std 0,%O0+8(%R0)\n"
" std 2,24(%1)\n" " std 2,%O0+24(%R0)\n"
" std 4,40(%1)\n" " std 4,%O0+40(%R0)\n"
" std 6,56(%1)" " std 6,%O0+56(%R0)"
: "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory"); : "=Q" (*fpregs) : "Q" (*fpregs));
if (!MACHINE_HAS_IEEE) if (!MACHINE_HAS_IEEE)
return; return;
asm volatile( asm volatile(
" stfpc 0(%1)\n" " stfpc %0\n"
" std 1,16(%1)\n" " std 1,%O0+16(%R0)\n"
" std 3,32(%1)\n" " std 3,%O0+32(%R0)\n"
" std 5,48(%1)\n" " std 5,%O0+48(%R0)\n"
" std 7,64(%1)\n" " std 7,%O0+64(%R0)\n"
" std 8,72(%1)\n" " std 8,%O0+72(%R0)\n"
" std 9,80(%1)\n" " std 9,%O0+80(%R0)\n"
" std 10,88(%1)\n" " std 10,%O0+88(%R0)\n"
" std 11,96(%1)\n" " std 11,%O0+96(%R0)\n"
" std 12,104(%1)\n" " std 12,%O0+104(%R0)\n"
" std 13,112(%1)\n" " std 13,%O0+112(%R0)\n"
" std 14,120(%1)\n" " std 14,%O0+120(%R0)\n"
" std 15,128(%1)\n" " std 15,%O0+128(%R0)\n"
: "=m" (*fpregs) : "a" (fpregs), "m" (*fpregs) : "memory"); : "=Q" (*fpregs) : "Q" (*fpregs));
} }
static inline void restore_fp_regs(s390_fp_regs *fpregs) static inline void restore_fp_regs(s390_fp_regs *fpregs)
{ {
asm volatile( asm volatile(
" ld 0,8(%0)\n" " ld 0,%O0+8(%R0)\n"
" ld 2,24(%0)\n" " ld 2,%O0+24(%R0)\n"
" ld 4,40(%0)\n" " ld 4,%O0+40(%R0)\n"
" ld 6,56(%0)" " ld 6,%O0+56(%R0)"
: : "a" (fpregs), "m" (*fpregs)); : : "Q" (*fpregs));
if (!MACHINE_HAS_IEEE) if (!MACHINE_HAS_IEEE)
return; return;
asm volatile( asm volatile(
" lfpc 0(%0)\n" " lfpc %0\n"
" ld 1,16(%0)\n" " ld 1,%O0+16(%R0)\n"
" ld 3,32(%0)\n" " ld 3,%O0+32(%R0)\n"
" ld 5,48(%0)\n" " ld 5,%O0+48(%R0)\n"
" ld 7,64(%0)\n" " ld 7,%O0+64(%R0)\n"
" ld 8,72(%0)\n" " ld 8,%O0+72(%R0)\n"
" ld 9,80(%0)\n" " ld 9,%O0+80(%R0)\n"
" ld 10,88(%0)\n" " ld 10,%O0+88(%R0)\n"
" ld 11,96(%0)\n" " ld 11,%O0+96(%R0)\n"
" ld 12,104(%0)\n" " ld 12,%O0+104(%R0)\n"
" ld 13,112(%0)\n" " ld 13,%O0+112(%R0)\n"
" ld 14,120(%0)\n" " ld 14,%O0+120(%R0)\n"
" ld 15,128(%0)\n" " ld 15,%O0+128(%R0)\n"
: : "a" (fpregs), "m" (*fpregs)); : : "Q" (*fpregs));
} }
static inline void save_access_regs(unsigned int *acrs) static inline void save_access_regs(unsigned int *acrs)
{ {
asm volatile("stam 0,15,0(%0)" : : "a" (acrs) : "memory"); asm volatile("stam 0,15,%0" : "=Q" (*acrs));
} }
static inline void restore_access_regs(unsigned int *acrs) static inline void restore_access_regs(unsigned int *acrs)
{ {
asm volatile("lam 0,15,0(%0)" : : "a" (acrs)); asm volatile("lam 0,15,%0" : : "Q" (*acrs));
} }
#define switch_to(prev,next,last) do { \ #define switch_to(prev,next,last) do { \
...@@ -139,48 +139,48 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size) ...@@ -139,48 +139,48 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
shift = (3 ^ (addr & 3)) << 3; shift = (3 ^ (addr & 3)) << 3;
addr ^= addr & 3; addr ^= addr & 3;
asm volatile( asm volatile(
" l %0,0(%4)\n" " l %0,%4\n"
"0: lr 0,%0\n" "0: lr 0,%0\n"
" nr 0,%3\n" " nr 0,%3\n"
" or 0,%2\n" " or 0,%2\n"
" cs %0,0,0(%4)\n" " cs %0,0,%4\n"
" jl 0b\n" " jl 0b\n"
: "=&d" (old), "=m" (*(int *) addr) : "=&d" (old), "=Q" (*(int *) addr)
: "d" (x << shift), "d" (~(255 << shift)), "a" (addr), : "d" (x << shift), "d" (~(255 << shift)),
"m" (*(int *) addr) : "memory", "cc", "0"); "Q" (*(int *) addr) : "memory", "cc", "0");
return old >> shift; return old >> shift;
case 2: case 2:
addr = (unsigned long) ptr; addr = (unsigned long) ptr;
shift = (2 ^ (addr & 2)) << 3; shift = (2 ^ (addr & 2)) << 3;
addr ^= addr & 2; addr ^= addr & 2;
asm volatile( asm volatile(
" l %0,0(%4)\n" " l %0,%4\n"
"0: lr 0,%0\n" "0: lr 0,%0\n"
" nr 0,%3\n" " nr 0,%3\n"
" or 0,%2\n" " or 0,%2\n"
" cs %0,0,0(%4)\n" " cs %0,0,%4\n"
" jl 0b\n" " jl 0b\n"
: "=&d" (old), "=m" (*(int *) addr) : "=&d" (old), "=Q" (*(int *) addr)
: "d" (x << shift), "d" (~(65535 << shift)), "a" (addr), : "d" (x << shift), "d" (~(65535 << shift)),
"m" (*(int *) addr) : "memory", "cc", "0"); "Q" (*(int *) addr) : "memory", "cc", "0");
return old >> shift; return old >> shift;
case 4: case 4:
asm volatile( asm volatile(
" l %0,0(%3)\n" " l %0,%3\n"
"0: cs %0,%2,0(%3)\n" "0: cs %0,%2,%3\n"
" jl 0b\n" " jl 0b\n"
: "=&d" (old), "=m" (*(int *) ptr) : "=&d" (old), "=Q" (*(int *) ptr)
: "d" (x), "a" (ptr), "m" (*(int *) ptr) : "d" (x), "Q" (*(int *) ptr)
: "memory", "cc"); : "memory", "cc");
return old; return old;
#ifdef __s390x__ #ifdef __s390x__
case 8: case 8:
asm volatile( asm volatile(
" lg %0,0(%3)\n" " lg %0,%3\n"
"0: csg %0,%2,0(%3)\n" "0: csg %0,%2,%3\n"
" jl 0b\n" " jl 0b\n"
: "=&d" (old), "=m" (*(long *) ptr) : "=&d" (old), "=m" (*(long *) ptr)
: "d" (x), "a" (ptr), "m" (*(long *) ptr) : "d" (x), "Q" (*(long *) ptr)
: "memory", "cc"); : "memory", "cc");
return old; return old;
#endif /* __s390x__ */ #endif /* __s390x__ */
...@@ -215,20 +215,20 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -215,20 +215,20 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
shift = (3 ^ (addr & 3)) << 3; shift = (3 ^ (addr & 3)) << 3;
addr ^= addr & 3; addr ^= addr & 3;
asm volatile( asm volatile(
" l %0,0(%4)\n" " l %0,%2\n"
"0: nr %0,%5\n" "0: nr %0,%5\n"
" lr %1,%0\n" " lr %1,%0\n"
" or %0,%2\n" " or %0,%2\n"
" or %1,%3\n" " or %1,%3\n"
" cs %0,%1,0(%4)\n" " cs %0,%1,%2\n"
" jnl 1f\n" " jnl 1f\n"
" xr %1,%0\n" " xr %1,%0\n"
" nr %1,%5\n" " nr %1,%5\n"
" jnz 0b\n" " jnz 0b\n"
"1:" "1:"
: "=&d" (prev), "=&d" (tmp) : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
: "d" (old << shift), "d" (new << shift), "a" (ptr), : "d" (old << shift), "d" (new << shift),
"d" (~(255 << shift)) "d" (~(255 << shift)), "Q" (*(int *) ptr)
: "memory", "cc"); : "memory", "cc");
return prev >> shift; return prev >> shift;
case 2: case 2:
...@@ -236,33 +236,35 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -236,33 +236,35 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
shift = (2 ^ (addr & 2)) << 3; shift = (2 ^ (addr & 2)) << 3;
addr ^= addr & 2; addr ^= addr & 2;
asm volatile( asm volatile(
" l %0,0(%4)\n" " l %0,%2\n"
"0: nr %0,%5\n" "0: nr %0,%5\n"
" lr %1,%0\n" " lr %1,%0\n"
" or %0,%2\n" " or %0,%2\n"
" or %1,%3\n" " or %1,%3\n"
" cs %0,%1,0(%4)\n" " cs %0,%1,%2\n"
" jnl 1f\n" " jnl 1f\n"
" xr %1,%0\n" " xr %1,%0\n"
" nr %1,%5\n" " nr %1,%5\n"
" jnz 0b\n" " jnz 0b\n"
"1:" "1:"
: "=&d" (prev), "=&d" (tmp) : "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
: "d" (old << shift), "d" (new << shift), "a" (ptr), : "d" (old << shift), "d" (new << shift),
"d" (~(65535 << shift)) "d" (~(65535 << shift)), "Q" (*(int *) ptr)
: "memory", "cc"); : "memory", "cc");
return prev >> shift; return prev >> shift;
case 4: case 4:
asm volatile( asm volatile(
" cs %0,%2,0(%3)\n" " cs %0,%3,%1\n"
: "=&d" (prev) : "0" (old), "d" (new), "a" (ptr) : "=&d" (prev), "=Q" (*(int *) ptr)
: "0" (old), "d" (new), "Q" (*(int *) ptr)
: "memory", "cc"); : "memory", "cc");
return prev; return prev;
#ifdef __s390x__ #ifdef __s390x__
case 8: case 8:
asm volatile( asm volatile(
" csg %0,%2,0(%3)\n" " csg %0,%3,%1\n"
: "=&d" (prev) : "0" (old), "d" (new), "a" (ptr) : "=&d" (prev), "=Q" (*(long *) ptr)
: "0" (old), "d" (new), "Q" (*(long *) ptr)
: "memory", "cc"); : "memory", "cc");
return prev; return prev;
#endif /* __s390x__ */ #endif /* __s390x__ */
...@@ -302,17 +304,17 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -302,17 +304,17 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#define __ctl_load(array, low, high) ({ \ #define __ctl_load(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \ typedef struct { char _[sizeof(array)]; } addrtype; \
asm volatile( \ asm volatile( \
" lctlg %1,%2,0(%0)\n" \ " lctlg %1,%2,%0\n" \
: : "a" (&array), "i" (low), "i" (high), \ : : "Q" (*(addrtype *)(&array)), \
"m" (*(addrtype *)(&array))); \ "i" (low), "i" (high)); \
}) })
#define __ctl_store(array, low, high) ({ \ #define __ctl_store(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \ typedef struct { char _[sizeof(array)]; } addrtype; \
asm volatile( \ asm volatile( \
" stctg %2,%3,0(%1)\n" \ " stctg %1,%2,%0\n" \
: "=m" (*(addrtype *)(&array)) \ : "=Q" (*(addrtype *)(&array)) \
: "a" (&array), "i" (low), "i" (high)); \ : "i" (low), "i" (high)); \
}) })
#else /* __s390x__ */ #else /* __s390x__ */
...@@ -320,17 +322,17 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -320,17 +322,17 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#define __ctl_load(array, low, high) ({ \ #define __ctl_load(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \ typedef struct { char _[sizeof(array)]; } addrtype; \
asm volatile( \ asm volatile( \
" lctl %1,%2,0(%0)\n" \ " lctl %1,%2,%0\n" \
: : "a" (&array), "i" (low), "i" (high), \ : : "Q" (*(addrtype *)(&array)), \
"m" (*(addrtype *)(&array))); \ "i" (low), "i" (high)); \
}) })
#define __ctl_store(array, low, high) ({ \ #define __ctl_store(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \ typedef struct { char _[sizeof(array)]; } addrtype; \
asm volatile( \ asm volatile( \
" stctl %2,%3,0(%1)\n" \ " stctl %1,%2,%0\n" \
: "=m" (*(addrtype *)(&array)) \ : "=Q" (*(addrtype *)(&array)) \
: "a" (&array), "i" (low), "i" (high)); \ : "i" (low), "i" (high)); \
}) })
#endif /* __s390x__ */ #endif /* __s390x__ */
......
...@@ -73,7 +73,7 @@ struct thread_info { ...@@ -73,7 +73,7 @@ struct thread_info {
/* how to get the thread information struct from C */ /* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void) static inline struct thread_info *current_thread_info(void)
{ {
return (struct thread_info *)((*(unsigned long *) __LC_KERNEL_STACK)-THREAD_SIZE); return (struct thread_info *)(S390_lowcore.kernel_stack - THREAD_SIZE);
} }
#define THREAD_SIZE_ORDER THREAD_ORDER #define THREAD_SIZE_ORDER THREAD_ORDER
......
...@@ -20,10 +20,10 @@ static inline int set_clock(__u64 time) ...@@ -20,10 +20,10 @@ static inline int set_clock(__u64 time)
int cc; int cc;
asm volatile( asm volatile(
" sck 0(%2)\n" " sck %1\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
: "=d" (cc) : "m" (time), "a" (&time) : "cc"); : "=d" (cc) : "Q" (time) : "cc");
return cc; return cc;
} }
...@@ -32,21 +32,21 @@ static inline int store_clock(__u64 *time) ...@@ -32,21 +32,21 @@ static inline int store_clock(__u64 *time)
int cc; int cc;
asm volatile( asm volatile(
" stck 0(%2)\n" " stck %1\n"
" ipm %0\n" " ipm %0\n"
" srl %0,28\n" " srl %0,28\n"
: "=d" (cc), "=m" (*time) : "a" (time) : "cc"); : "=d" (cc), "=Q" (*time) : : "cc");
return cc; return cc;
} }
static inline void set_clock_comparator(__u64 time) static inline void set_clock_comparator(__u64 time)
{ {
asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time)); asm volatile("sckc %0" : : "Q" (time));
} }
static inline void store_clock_comparator(__u64 *time) static inline void store_clock_comparator(__u64 *time)
{ {
asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time)); asm volatile("stckc %0" : "=Q" (*time));
} }
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
...@@ -57,11 +57,7 @@ static inline unsigned long long get_clock (void) ...@@ -57,11 +57,7 @@ static inline unsigned long long get_clock (void)
{ {
unsigned long long clk; unsigned long long clk;
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
asm volatile("stck %0" : "=Q" (clk) : : "cc"); asm volatile("stck %0" : "=Q" (clk) : : "cc");
#else /* __GNUC__ */
asm volatile("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
#endif /* __GNUC__ */
return clk; return clk;
} }
...@@ -69,13 +65,7 @@ static inline unsigned long long get_clock_xt(void) ...@@ -69,13 +65,7 @@ static inline unsigned long long get_clock_xt(void)
{ {
unsigned char clk[16]; unsigned char clk[16];
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
asm volatile("stcke %0" : "=Q" (clk) : : "cc"); asm volatile("stcke %0" : "=Q" (clk) : : "cc");
#else /* __GNUC__ */
asm volatile("stcke 0(%1)" : "=m" (clk)
: "a" (clk) : "cc");
#endif /* __GNUC__ */
return *((unsigned long long *)&clk[1]); return *((unsigned long long *)&clk[1]);
} }
......
...@@ -265,6 +265,12 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) ...@@ -265,6 +265,12 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
return uaccess.copy_from_user(n, from, to); return uaccess.copy_from_user(n, from, to);
} }
extern void copy_from_user_overflow(void)
#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
__compiletime_warning("copy_from_user() buffer size is not provably correct")
#endif
;
/** /**
* copy_from_user: - Copy a block of data from user space. * copy_from_user: - Copy a block of data from user space.
* @to: Destination address, in kernel space. * @to: Destination address, in kernel space.
...@@ -284,7 +290,13 @@ __copy_from_user(void *to, const void __user *from, unsigned long n) ...@@ -284,7 +290,13 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
static inline unsigned long __must_check static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n) copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
unsigned int sz = __compiletime_object_size(to);
might_fault(); might_fault();
if (unlikely(sz != -1 && sz < n)) {
copy_from_user_overflow();
return n;
}
if (access_ok(VERIFY_READ, from, n)) if (access_ok(VERIFY_READ, from, n))
n = __copy_from_user(to, from, n); n = __copy_from_user(to, from, n);
else else
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define VDSO32_LBASE 0 #define VDSO32_LBASE 0
#define VDSO64_LBASE 0 #define VDSO64_LBASE 0
#define VDSO_VERSION_STRING LINUX_2.6.26 #define VDSO_VERSION_STRING LINUX_2.6.29
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
...@@ -29,9 +29,12 @@ obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) ...@@ -29,9 +29,12 @@ obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
extra-y += head.o init_task.o vmlinux.lds extra-y += head.o init_task.o vmlinux.lds
extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o)
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
obj-$(CONFIG_SMP) += smp.o topology.o obj-$(CONFIG_SMP) += smp.o topology.o
obj-$(CONFIG_SMP) += $(if $(CONFIG_64BIT),switch_cpu64.o, \
switch_cpu.o)
obj-$(CONFIG_HIBERNATION) += suspend.o swsusp_asm64.o obj-$(CONFIG_HIBERNATION) += suspend.o swsusp_asm64.o
obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDIT) += audit.o
compat-obj-$(CONFIG_AUDIT) += compat_audit.o compat-obj-$(CONFIG_AUDIT) += compat_audit.o
......
...@@ -4,18 +4,27 @@ ...@@ -4,18 +4,27 @@
* and format the required data. * and format the required data.
*/ */
#include <linux/sched.h> #define ASM_OFFSETS_C
#include <linux/kbuild.h> #include <linux/kbuild.h>
#include <linux/sched.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/sigp.h> #include <asm/sigp.h>
/*
* Make sure that the compiler is new enough. We want a compiler that
* is known to work with the "Q" assembler constraint.
*/
#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
#error Your compiler is too old; please use version 3.3.3 or newer
#endif
int main(void) int main(void)
{ {
DEFINE(__THREAD_info, offsetof(struct task_struct, stack)); DEFINE(__THREAD_info, offsetof(struct task_struct, stack));
DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp)); DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp));
DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info)); DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info));
DEFINE(__THREAD_mm_segment, DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment));
offsetof(struct task_struct, thread.mm_segment));
BLANK(); BLANK();
DEFINE(__TASK_pid, offsetof(struct task_struct, pid)); DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
BLANK(); BLANK();
...@@ -52,18 +61,94 @@ int main(void) ...@@ -52,18 +61,94 @@ int main(void)
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest)); DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available)); DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
DEFINE(__VDSO_ECTG_BASE, DEFINE(__VDSO_ECTG_BASE, offsetof(struct vdso_per_cpu_data, ectg_timer_base));
offsetof(struct vdso_per_cpu_data, ectg_timer_base)); DEFINE(__VDSO_ECTG_USER, offsetof(struct vdso_per_cpu_data, ectg_user_time));
DEFINE(__VDSO_ECTG_USER,
offsetof(struct vdso_per_cpu_data, ectg_user_time));
/* constants used by the vdso */ /* constants used by the vdso */
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
BLANK();
/* constants for SIGP */ /* constants for SIGP */
DEFINE(__SIGP_STOP, sigp_stop); DEFINE(__SIGP_STOP, sigp_stop);
DEFINE(__SIGP_RESTART, sigp_restart); DEFINE(__SIGP_RESTART, sigp_restart);
DEFINE(__SIGP_SENSE, sigp_sense); DEFINE(__SIGP_SENSE, sigp_sense);
DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset); DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset);
BLANK();
/* lowcore offsets */
DEFINE(__LC_EXT_PARAMS, offsetof(struct _lowcore, ext_params));
DEFINE(__LC_CPU_ADDRESS, offsetof(struct _lowcore, cpu_addr));
DEFINE(__LC_EXT_INT_CODE, offsetof(struct _lowcore, ext_int_code));
DEFINE(__LC_SVC_ILC, offsetof(struct _lowcore, svc_ilc));
DEFINE(__LC_SVC_INT_CODE, offsetof(struct _lowcore, svc_code));
DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc));
DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code));
DEFINE(__LC_PER_ATMID, offsetof(struct _lowcore, per_perc_atmid));
DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address));
DEFINE(__LC_PER_ACCESS_ID, offsetof(struct _lowcore, per_access_id));
DEFINE(__LC_AR_MODE_ID, offsetof(struct _lowcore, ar_access_id));
DEFINE(__LC_SUBCHANNEL_ID, offsetof(struct _lowcore, subchannel_id));
DEFINE(__LC_SUBCHANNEL_NR, offsetof(struct _lowcore, subchannel_nr));
DEFINE(__LC_IO_INT_PARM, offsetof(struct _lowcore, io_int_parm));
DEFINE(__LC_IO_INT_WORD, offsetof(struct _lowcore, io_int_word));
DEFINE(__LC_STFL_FAC_LIST, offsetof(struct _lowcore, stfl_fac_list));
DEFINE(__LC_MCCK_CODE, offsetof(struct _lowcore, mcck_interruption_code));
DEFINE(__LC_DUMP_REIPL, offsetof(struct _lowcore, ipib));
BLANK();
DEFINE(__LC_RST_NEW_PSW, offsetof(struct _lowcore, restart_psw));
DEFINE(__LC_RST_OLD_PSW, offsetof(struct _lowcore, restart_old_psw));
DEFINE(__LC_EXT_OLD_PSW, offsetof(struct _lowcore, external_old_psw));
DEFINE(__LC_SVC_OLD_PSW, offsetof(struct _lowcore, svc_old_psw));
DEFINE(__LC_PGM_OLD_PSW, offsetof(struct _lowcore, program_old_psw));
DEFINE(__LC_MCK_OLD_PSW, offsetof(struct _lowcore, mcck_old_psw));
DEFINE(__LC_IO_OLD_PSW, offsetof(struct _lowcore, io_old_psw));
DEFINE(__LC_EXT_NEW_PSW, offsetof(struct _lowcore, external_new_psw));
DEFINE(__LC_SVC_NEW_PSW, offsetof(struct _lowcore, svc_new_psw));
DEFINE(__LC_PGM_NEW_PSW, offsetof(struct _lowcore, program_new_psw));
DEFINE(__LC_MCK_NEW_PSW, offsetof(struct _lowcore, mcck_new_psw));
DEFINE(__LC_IO_NEW_PSW, offsetof(struct _lowcore, io_new_psw));
DEFINE(__LC_SAVE_AREA, offsetof(struct _lowcore, save_area));
DEFINE(__LC_RETURN_PSW, offsetof(struct _lowcore, return_psw));
DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw));
DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer));
DEFINE(__LC_ASYNC_ENTER_TIMER, offsetof(struct _lowcore, async_enter_timer));
DEFINE(__LC_EXIT_TIMER, offsetof(struct _lowcore, exit_timer));
DEFINE(__LC_USER_TIMER, offsetof(struct _lowcore, user_timer));
DEFINE(__LC_SYSTEM_TIMER, offsetof(struct _lowcore, system_timer));
DEFINE(__LC_STEAL_TIMER, offsetof(struct _lowcore, steal_timer));
DEFINE(__LC_LAST_UPDATE_TIMER, offsetof(struct _lowcore, last_update_timer));
DEFINE(__LC_LAST_UPDATE_CLOCK, offsetof(struct _lowcore, last_update_clock));
DEFINE(__LC_CURRENT, offsetof(struct _lowcore, current_task));
DEFINE(__LC_THREAD_INFO, offsetof(struct _lowcore, thread_info));
DEFINE(__LC_KERNEL_STACK, offsetof(struct _lowcore, kernel_stack));
DEFINE(__LC_ASYNC_STACK, offsetof(struct _lowcore, async_stack));
DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce));
DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce));
DEFINE(__LC_CPUID, offsetof(struct _lowcore, cpu_id));
DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));
DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func));
DEFINE(__LC_IRB, offsetof(struct _lowcore, irb));
DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area));
DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area));
DEFINE(__LC_PSW_SAVE_AREA, offsetof(struct _lowcore, psw_save_area));
DEFINE(__LC_PREFIX_SAVE_AREA, offsetof(struct _lowcore, prefixreg_save_area));
DEFINE(__LC_AREGS_SAVE_AREA, offsetof(struct _lowcore, access_regs_save_area));
DEFINE(__LC_FPREGS_SAVE_AREA, offsetof(struct _lowcore, floating_pt_save_area));
DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
#ifdef CONFIG_32BIT
DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params));
DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
#else /* CONFIG_32BIT */
DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2));
DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));
DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area));
DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
#endif /* CONFIG_32BIT */
return 0; return 0;
} }
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
* Michael Holzheu <holzheu@de.ibm.com> * Michael Holzheu <holzheu@de.ibm.com>
*/ */
#include <asm/asm-offsets.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/lowcore.h>
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
......
This diff is collapsed.
...@@ -214,10 +214,13 @@ static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); ...@@ -214,10 +214,13 @@ static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
static noinline __init void detect_machine_type(void) static noinline __init void detect_machine_type(void)
{ {
/* No VM information? Looks like LPAR */ /* Check current-configuration-level */
if (stsi(&vmms, 3, 2, 2) == -ENOSYS) if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) {
S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR;
return; return;
if (!vmms.count) }
/* Get virtual-machine cpu information. */
if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count)
return; return;
/* Running under KVM? If not we assume z/VM */ /* Running under KVM? If not we assume z/VM */
...@@ -402,8 +405,19 @@ static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t)) ...@@ -402,8 +405,19 @@ static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t))
static void __init setup_boot_command_line(void) static void __init setup_boot_command_line(void)
{ {
int i;
/* convert arch command line to ascii */
for (i = 0; i < ARCH_COMMAND_LINE_SIZE; i++)
if (COMMAND_LINE[i] & 0x80)
break;
if (i < ARCH_COMMAND_LINE_SIZE)
EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
COMMAND_LINE[ARCH_COMMAND_LINE_SIZE-1] = 0;
/* copy arch command line */ /* copy arch command line */
strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); strlcpy(boot_command_line, strstrip(COMMAND_LINE),
ARCH_COMMAND_LINE_SIZE);
/* append IPL PARM data to the boot command line */ /* append IPL PARM data to the boot command line */
if (MACHINE_IS_VM) if (MACHINE_IS_VM)
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
......
...@@ -9,11 +9,9 @@ ...@@ -9,11 +9,9 @@
* Heiko Carstens <heiko.carstens@de.ibm.com> * Heiko Carstens <heiko.carstens@de.ibm.com>
*/ */
#include <linux/sys.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include <trace/syscall.h> #include <trace/syscall.h>
#include <asm/lowcore.h> #include <asm/asm-offsets.h>
#ifdef CONFIG_DYNAMIC_FTRACE #ifdef CONFIG_DYNAMIC_FTRACE
......
/* /*
* Copyright IBM Corp. 1999,2009 * Copyright IBM Corp. 1999,2010
* *
* Author(s): Hartmut Penner <hp@de.ibm.com> * Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
...@@ -22,12 +22,9 @@ ...@@ -22,12 +22,9 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <asm/setup.h>
#include <asm/lowcore.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/cpu.h>
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#define ARCH_OFFSET 4 #define ARCH_OFFSET 4
...@@ -288,19 +285,7 @@ iplstart: ...@@ -288,19 +285,7 @@ iplstart:
bz .Lagain1 # skip dateset trailer bz .Lagain1 # skip dateset trailer
la %r5,0(%r4,%r2) la %r5,0(%r4,%r2)
lr %r3,%r2 lr %r3,%r2
.Lidebc: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
tm 0(%r5),0x80 # high order bit set ?
bo .Ldocv # yes -> convert from EBCDIC
ahi %r5,-1
bct %r3,.Lidebc
b .Lnocv
.Ldocv:
l %r3,.Lcvtab
tr 0(256,%r4),0(%r3) # convert parameters to ascii
tr 256(256,%r4),0(%r3)
tr 512(256,%r4),0(%r3)
tr 768(122,%r4),0(%r3)
.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
mvc 0(256,%r3),0(%r4) mvc 0(256,%r3),0(%r4)
mvc 256(256,%r3),256(%r4) mvc 256(256,%r3),256(%r4)
mvc 512(256,%r3),512(%r4) mvc 512(256,%r3),512(%r4)
...@@ -384,7 +369,6 @@ iplstart: ...@@ -384,7 +369,6 @@ iplstart:
.Linitrd:.long _end + 0x400000 # default address of initrd .Linitrd:.long _end + 0x400000 # default address of initrd
.Lparm: .long PARMAREA .Lparm: .long PARMAREA
.Lstartup: .long startup .Lstartup: .long startup
.Lcvtab:.long _ebcasc # ebcdic to ascii table
.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 .Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
.byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
.byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
...@@ -417,13 +401,10 @@ start: ...@@ -417,13 +401,10 @@ start:
.sk8x8: .sk8x8:
mvc 0(240,%r8),0(%r9) # copy iplparms into buffer mvc 0(240,%r8),0(%r9) # copy iplparms into buffer
.gotr: .gotr:
l %r10,.tbl # EBCDIC to ASCII table
tr 0(240,%r8),0(%r10)
slr %r0,%r0 slr %r0,%r0
st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11) st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11) st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
j startup # continue with startup j startup # continue with startup
.tbl: .long _ebcasc # translate table
.cmd: .long COMMAND_LINE # address of command line buffer .cmd: .long COMMAND_LINE # address of command line buffer
.parm: .long PARMAREA .parm: .long PARMAREA
.lowcase: .lowcase:
...@@ -467,16 +448,15 @@ start: ...@@ -467,16 +448,15 @@ start:
# or linload or SALIPL # or linload or SALIPL
# #
.org 0x10000 .org 0x10000
startup:basr %r13,0 # get base .globl startup
startup:
basr %r13,0 # get base
.LPG0: .LPG0:
xc 0x200(256),0x200 # partially clear lowcore xc 0x200(256),0x200 # partially clear lowcore
xc 0x300(256),0x300 xc 0x300(256),0x300
l %r1,5f-.LPG0(%r13) stck __LC_LAST_UPDATE_CLOCK
stck 0(%r1) spt 5f-.LPG0(%r13)
spt 6f-.LPG0(%r13) mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
mvc __LC_LAST_UPDATE_CLOCK(8),0(%r1)
mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
mvc __LC_EXIT_TIMER(8),5f-.LPG0(%r13)
#ifndef CONFIG_MARCH_G5 #ifndef CONFIG_MARCH_G5
# check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10} # check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
...@@ -494,7 +474,6 @@ startup:basr %r13,0 # get base ...@@ -494,7 +474,6 @@ startup:basr %r13,0 # get base
cl %r0,2f+12-.LPG0(%r13) cl %r0,2f+12-.LPG0(%r13)
je 3f je 3f
1: l %r15,.Lstack-.LPG0(%r13) 1: l %r15,.Lstack-.LPG0(%r13)
ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
ahi %r15,-96 ahi %r15,-96
la %r2,.Lals_string-.LPG0(%r13) la %r2,.Lals_string-.LPG0(%r13)
l %r3,.Lsclp_print-.LPG0(%r13) l %r3,.Lsclp_print-.LPG0(%r13)
...@@ -505,7 +484,7 @@ startup:basr %r13,0 # get base ...@@ -505,7 +484,7 @@ startup:basr %r13,0 # get base
.Lsclp_print: .Lsclp_print:
.long _sclp_print_early .long _sclp_print_early
.Lstack: .Lstack:
.long init_thread_union .long 0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
.align 16 .align 16
2: .long 0x000a0000,0x8badcccc 2: .long 0x000a0000,0x8badcccc
#if defined(CONFIG_64BIT) #if defined(CONFIG_64BIT)
...@@ -532,13 +511,22 @@ startup:basr %r13,0 # get base ...@@ -532,13 +511,22 @@ startup:basr %r13,0 # get base
3: 3:
#endif #endif
#ifdef CONFIG_64BIT
mvi __LC_AR_MODE_ID,1 # set esame flag
slr %r0,%r0 # set cpuid to zero
lhi %r1,2 # mode 2 = esame (dump)
sigp %r1,%r0,0x12 # switch to esame mode
sam64 # switch to 64 bit mode
jg startup_continue
#else
mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
l %r13,4f-.LPG0(%r13) l %r13,4f-.LPG0(%r13)
b 0(%r13) b 0(%r13)
.align 4 .align 8
4: .long startup_continue 4: .long startup_continue
5: .long sched_clock_base_cc #endif
.align 8 .align 8
6: .long 0x7fffffff,0xffffffff 5: .long 0x7fffffff,0xffffffff
# #
# params at 10400 (setup.h) # params at 10400 (setup.h)
...@@ -552,8 +540,4 @@ startup:basr %r13,0 # get base ...@@ -552,8 +540,4 @@ startup:basr %r13,0 # get base
.byte "root=/dev/ram0 ro" .byte "root=/dev/ram0 ro"
.byte 0 .byte 0
#ifdef CONFIG_64BIT .org 0x11000
#include "head64.S"
#else
#include "head31.S"
#endif
/* /*
* arch/s390/kernel/head31.S * arch/s390/kernel/head31.S
* *
* Copyright (C) IBM Corp. 2005,2006 * Copyright (C) IBM Corp. 2005,2010
* *
* Author(s): Hartmut Penner <hp@de.ibm.com> * Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
...@@ -10,13 +10,19 @@ ...@@ -10,13 +10,19 @@
* *
*/ */
.org 0x11000 #include <linux/init.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
__HEAD
.globl startup_continue
startup_continue: startup_continue:
basr %r13,0 # get base basr %r13,0 # get base
.LPG1: .LPG1:
mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0) l %r1,.Lbase_cc-.LPG1(%r13)
mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK
lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore # move IPL device to lowcore
...@@ -69,10 +75,12 @@ startup_continue: ...@@ -69,10 +75,12 @@ startup_continue:
.Lduald:.rept 8 .Lduald:.rept 8
.long 0x80000000,0,0,0 # invalid access-list entries .long 0x80000000,0,0,0 # invalid access-list entries
.endr .endr
.Lbase_cc:
.long sched_clock_base_cc
.org 0x12000
.globl _ehead .globl _ehead
_ehead: _ehead:
#ifdef CONFIG_SHARED_KERNEL #ifdef CONFIG_SHARED_KERNEL
.org 0x100000 .org 0x100000
#endif #endif
......
/* /*
* arch/s390/kernel/head64.S * arch/s390/kernel/head64.S
* *
* Copyright (C) IBM Corp. 1999,2006 * Copyright (C) IBM Corp. 1999,2010
* *
* Author(s): Hartmut Penner <hp@de.ibm.com> * Author(s): Hartmut Penner <hp@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
...@@ -10,80 +10,17 @@ ...@@ -10,80 +10,17 @@
* *
*/ */
.org 0x11000 #include <linux/init.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/page.h>
__HEAD
.globl startup_continue
startup_continue: startup_continue:
basr %r13,0 # get base larl %r1,sched_clock_base_cc
.LPG1: sll %r13,1 # remove high order bit mvc 0(8,%r1),__LC_LAST_UPDATE_CLOCK
srl %r13,1 larl %r13,.LPG1 # get base
#ifdef CONFIG_ZFCPDUMP
# check if we have been ipled using zfcp dump:
tm 0xb9,0x01 # test if subchannel is enabled
jno .nodump # subchannel disabled
l %r1,0xb8
la %r5,.Lipl_schib-.LPG1(%r13)
stsch 0(%r5) # get schib of subchannel
jne .nodump # schib not available
tm 5(%r5),0x01 # devno valid?
jno .nodump
tm 4(%r5),0x80 # qdio capable device?
jno .nodump
l %r2,20(%r0) # address of ipl parameter block
lhi %r3,0
ic %r3,0x148(%r2) # get opt field
chi %r3,0x20 # load with dump?
jne .nodump
# store all prefix registers in case of load with dump:
la %r7,0 # base register for 0 page
la %r8,0 # first cpu
l %r11,.Lpref_arr_ptr-.LPG1(%r13) # address of prefix array
ahi %r11,4 # skip boot cpu
lr %r12,%r11
ahi %r12,(CONFIG_NR_CPUS*4) # end of prefix array
stap .Lcurrent_cpu+2-.LPG1(%r13) # store current cpu addr
1:
cl %r8,.Lcurrent_cpu-.LPG1(%r13) # is ipl cpu ?
je 4f # if yes get next cpu
2:
lr %r9,%r7
sigp %r9,%r8,0x9 # stop & store status of cpu
brc 8,3f # accepted
brc 4,4f # status stored: next cpu
brc 2,2b # busy: try again
brc 1,4f # not op: next cpu
3:
mvc 0(4,%r11),264(%r7) # copy prefix register to prefix array
ahi %r11,4 # next element in prefix array
clr %r11,%r12
je 5f # no more space in prefix array
4:
ahi %r8,1 # next cpu (r8 += 1)
chi %r8,MAX_CPU_ADDRESS # is last possible cpu ?
jle 1b # jump if not last cpu
5:
lhi %r1,2 # mode 2 = esame (dump)
j 6f
.align 4
.Lipl_schib:
.rept 13
.long 0
.endr
.nodump:
lhi %r1,1 # mode 1 = esame (normal ipl)
6:
#else
lhi %r1,1 # mode 1 = esame (normal ipl)
#endif /* CONFIG_ZFCPDUMP */
mvi __LC_AR_MODE_ID,1 # set esame flag
slr %r0,%r0 # set cpuid to zero
sigp %r1,%r0,0x12 # switch to esame mode
sam64 # switch to 64 bit mode
llgfr %r13,%r13 # clear high-order half of base reg
lmh %r0,%r15,.Lzero64-.LPG1(%r13) # clear high-order half lmh %r0,%r15,.Lzero64-.LPG1(%r13) # clear high-order half
lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
...@@ -108,6 +45,7 @@ startup_continue: ...@@ -108,6 +45,7 @@ startup_continue:
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
.LPG1:
.Lentry:.quad 0x0000000180000000,_stext .Lentry:.quad 0x0000000180000000,_stext
.Lctl: .quad 0x04350002 # cr0: various things .Lctl: .quad 0x04350002 # cr0: various things
.quad 0 # cr1: primary space segment table .quad 0 # cr1: primary space segment table
...@@ -130,12 +68,6 @@ startup_continue: ...@@ -130,12 +68,6 @@ startup_continue:
.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
.Lnop: .long 0x07000700 .Lnop: .long 0x07000700
.Lzero64:.fill 16,4,0x0 .Lzero64:.fill 16,4,0x0
#ifdef CONFIG_ZFCPDUMP
.Lcurrent_cpu:
.long 0x0
.Lpref_arr_ptr:
.long zfcpdump_prefix_array
#endif /* CONFIG_ZFCPDUMP */
.Lparmaddr: .Lparmaddr:
.quad PARMAREA .quad PARMAREA
.align 64 .align 64
...@@ -146,9 +78,9 @@ startup_continue: ...@@ -146,9 +78,9 @@ startup_continue:
.long 0x80000000,0,0,0 # invalid access-list entries .long 0x80000000,0,0,0 # invalid access-list entries
.endr .endr
.org 0x12000
.globl _ehead .globl _ehead
_ehead: _ehead:
#ifdef CONFIG_SHARED_KERNEL #ifdef CONFIG_SHARED_KERNEL
.org 0x100000 .org 0x100000
#endif #endif
......
...@@ -553,7 +553,7 @@ static int __init ipl_register_fcp_files(void) ...@@ -553,7 +553,7 @@ static int __init ipl_register_fcp_files(void)
return rc; return rc;
} }
static void ipl_run(struct shutdown_trigger *trigger) static void __ipl_run(void *unused)
{ {
diag308(DIAG308_IPL, NULL); diag308(DIAG308_IPL, NULL);
if (MACHINE_IS_VM) if (MACHINE_IS_VM)
...@@ -562,6 +562,11 @@ static void ipl_run(struct shutdown_trigger *trigger) ...@@ -562,6 +562,11 @@ static void ipl_run(struct shutdown_trigger *trigger)
reipl_ccw_dev(&ipl_info.data.ccw.dev_id); reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
} }
static void ipl_run(struct shutdown_trigger *trigger)
{
smp_switch_to_ipl_cpu(__ipl_run, NULL);
}
static int __init ipl_init(void) static int __init ipl_init(void)
{ {
int rc; int rc;
...@@ -1039,7 +1044,7 @@ static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb, ...@@ -1039,7 +1044,7 @@ static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
sprintf(dst + pos, " PARM %s", vmparm); sprintf(dst + pos, " PARM %s", vmparm);
} }
static void reipl_run(struct shutdown_trigger *trigger) static void __reipl_run(void *unused)
{ {
struct ccw_dev_id devid; struct ccw_dev_id devid;
static char buf[128]; static char buf[128];
...@@ -1087,6 +1092,11 @@ static void reipl_run(struct shutdown_trigger *trigger) ...@@ -1087,6 +1092,11 @@ static void reipl_run(struct shutdown_trigger *trigger)
disabled_wait((unsigned long) __builtin_return_address(0)); disabled_wait((unsigned long) __builtin_return_address(0));
} }
static void reipl_run(struct shutdown_trigger *trigger)
{
smp_switch_to_ipl_cpu(__reipl_run, NULL);
}
static void reipl_block_ccw_init(struct ipl_parameter_block *ipb) static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
{ {
ipb->hdr.len = IPL_PARM_BLK_CCW_LEN; ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
...@@ -1369,20 +1379,18 @@ static struct kobj_attribute dump_type_attr = ...@@ -1369,20 +1379,18 @@ static struct kobj_attribute dump_type_attr =
static struct kset *dump_kset; static struct kset *dump_kset;
static void dump_run(struct shutdown_trigger *trigger) static void __dump_run(void *unused)
{ {
struct ccw_dev_id devid; struct ccw_dev_id devid;
static char buf[100]; static char buf[100];
switch (dump_method) { switch (dump_method) {
case DUMP_METHOD_CCW_CIO: case DUMP_METHOD_CCW_CIO:
smp_send_stop();
devid.devno = dump_block_ccw->ipl_info.ccw.devno; devid.devno = dump_block_ccw->ipl_info.ccw.devno;
devid.ssid = 0; devid.ssid = 0;
reipl_ccw_dev(&devid); reipl_ccw_dev(&devid);
break; break;
case DUMP_METHOD_CCW_VM: case DUMP_METHOD_CCW_VM:
smp_send_stop();
sprintf(buf, "STORE STATUS"); sprintf(buf, "STORE STATUS");
__cpcmd(buf, NULL, 0, NULL); __cpcmd(buf, NULL, 0, NULL);
sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
...@@ -1396,10 +1404,17 @@ static void dump_run(struct shutdown_trigger *trigger) ...@@ -1396,10 +1404,17 @@ static void dump_run(struct shutdown_trigger *trigger)
diag308(DIAG308_SET, dump_block_fcp); diag308(DIAG308_SET, dump_block_fcp);
diag308(DIAG308_DUMP, NULL); diag308(DIAG308_DUMP, NULL);
break; break;
case DUMP_METHOD_NONE: default:
return; break;
} }
printk(KERN_EMERG "Dump failed!\n"); }
static void dump_run(struct shutdown_trigger *trigger)
{
if (dump_method == DUMP_METHOD_NONE)
return;
smp_send_stop();
smp_switch_to_ipl_cpu(__dump_run, NULL);
} }
static int __init dump_ccw_init(void) static int __init dump_ccw_init(void)
...@@ -1577,7 +1592,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger) ...@@ -1577,7 +1592,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger)
static int vmcmd_init(void) static int vmcmd_init(void)
{ {
if (!MACHINE_IS_VM) if (!MACHINE_IS_VM)
return -ENOTSUPP; return -EOPNOTSUPP;
vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj); vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
if (!vmcmd_kset) if (!vmcmd_kset)
return -ENOMEM; return -ENOMEM;
...@@ -1595,7 +1610,7 @@ static void stop_run(struct shutdown_trigger *trigger) ...@@ -1595,7 +1610,7 @@ static void stop_run(struct shutdown_trigger *trigger)
{ {
if (strcmp(trigger->name, ON_PANIC_STR) == 0) if (strcmp(trigger->name, ON_PANIC_STR) == 0)
disabled_wait((unsigned long) __builtin_return_address(0)); disabled_wait((unsigned long) __builtin_return_address(0));
while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
cpu_relax(); cpu_relax();
for (;;); for (;;);
} }
...@@ -1902,7 +1917,6 @@ void __init ipl_update_parameters(void) ...@@ -1902,7 +1917,6 @@ void __init ipl_update_parameters(void)
void __init ipl_save_parameters(void) void __init ipl_save_parameters(void)
{ {
struct cio_iplinfo iplinfo; struct cio_iplinfo iplinfo;
unsigned int *ipl_ptr;
void *src, *dst; void *src, *dst;
if (cio_get_iplinfo(&iplinfo)) if (cio_get_iplinfo(&iplinfo))
...@@ -1913,11 +1927,10 @@ void __init ipl_save_parameters(void) ...@@ -1913,11 +1927,10 @@ void __init ipl_save_parameters(void)
if (!iplinfo.is_qdio) if (!iplinfo.is_qdio)
return; return;
ipl_flags |= IPL_PARMBLOCK_VALID; ipl_flags |= IPL_PARMBLOCK_VALID;
ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR; src = (void *)(unsigned long)S390_lowcore.ipl_parmblock_ptr;
src = (void *)(unsigned long)*ipl_ptr;
dst = (void *)IPL_PARMBLOCK_ORIGIN; dst = (void *)IPL_PARMBLOCK_ORIGIN;
memmove(dst, src, PAGE_SIZE); memmove(dst, src, PAGE_SIZE);
*ipl_ptr = IPL_PARMBLOCK_ORIGIN; S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
} }
static LIST_HEAD(rcall); static LIST_HEAD(rcall);
......
...@@ -54,11 +54,11 @@ void machine_shutdown(void) ...@@ -54,11 +54,11 @@ void machine_shutdown(void)
{ {
} }
void machine_kexec(struct kimage *image) static void __machine_kexec(void *data)
{ {
relocate_kernel_t data_mover; relocate_kernel_t data_mover;
struct kimage *image = data;
smp_send_stop();
pfault_fini(); pfault_fini();
s390_reset_system(); s390_reset_system();
...@@ -68,3 +68,9 @@ void machine_kexec(struct kimage *image) ...@@ -68,3 +68,9 @@ void machine_kexec(struct kimage *image)
(*data_mover)(&image->head, image->start); (*data_mover)(&image->head, image->start);
for (;;); for (;;);
} }
void machine_kexec(struct kimage *image)
{
smp_send_stop();
smp_switch_to_ipl_cpu(__machine_kexec, image);
}
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com) * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
*/ */
#include <asm/lowcore.h> #include <asm/asm-offsets.h>
# #
# do_reipl_asm # do_reipl_asm
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Denis Joseph Barrow, * Denis Joseph Barrow,
*/ */
#include <asm/lowcore.h> #include <asm/asm-offsets.h>
# #
# do_reipl_asm # do_reipl_asm
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
*/ */
LC_EXT_NEW_PSW = 0x58 # addr of ext int handler LC_EXT_NEW_PSW = 0x58 # addr of ext int handler
LC_EXT_NEW_PSW_64 = 0x1b0 # addr of ext int handler 64 bit
LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter LC_EXT_INT_PARAM = 0x80 # addr of ext int parameter
LC_EXT_INT_CODE = 0x86 # addr of ext int code LC_EXT_INT_CODE = 0x86 # addr of ext int code
LC_AR_MODE_ID = 0xa3
# #
# Subroutine which waits synchronously until either an external interruption # Subroutine which waits synchronously until either an external interruption
...@@ -30,8 +32,16 @@ _sclp_wait_int: ...@@ -30,8 +32,16 @@ _sclp_wait_int:
.LbaseS1: .LbaseS1:
ahi %r15,-96 # create stack frame ahi %r15,-96 # create stack frame
la %r8,LC_EXT_NEW_PSW # register int handler la %r8,LC_EXT_NEW_PSW # register int handler
mvc .LoldpswS1-.LbaseS1(8,%r13),0(%r8) la %r9,.LextpswS1-.LbaseS1(%r13)
mvc 0(8,%r8),.LextpswS1-.LbaseS1(%r13) #ifdef CONFIG_64BIT
tm LC_AR_MODE_ID,1
jno .Lesa1
la %r8,LC_EXT_NEW_PSW_64 # register int handler 64 bit
la %r9,.LextpswS1_64-.LbaseS1(%r13)
.Lesa1:
#endif
mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
mvc 0(16,%r8),0(%r9)
lhi %r6,0x0200 # cr mask for ext int (cr0.54) lhi %r6,0x0200 # cr mask for ext int (cr0.54)
ltr %r2,%r2 ltr %r2,%r2
jz .LsetctS1 jz .LsetctS1
...@@ -64,15 +74,19 @@ _sclp_wait_int: ...@@ -64,15 +74,19 @@ _sclp_wait_int:
.LtimeoutS1: .LtimeoutS1:
lctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # restore interrupt setting lctl %c0,%c0,.LctlS1-.LbaseS1(%r13) # restore interrupt setting
# restore old handler # restore old handler
mvc 0(8,%r8),.LoldpswS1-.LbaseS1(%r13) mvc 0(16,%r8),.LoldpswS1-.LbaseS1(%r13)
lm %r6,%r15,120(%r15) # restore registers lm %r6,%r15,120(%r15) # restore registers
br %r14 # return to caller br %r14 # return to caller
.align 8 .align 8
.LoldpswS1: .LoldpswS1:
.long 0, 0 # old ext int PSW .long 0, 0, 0, 0 # old ext int PSW
.LextpswS1: .LextpswS1:
.long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int .long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
#ifdef CONFIG_64BIT
.LextpswS1_64:
.quad 0x0000000180000000, .LwaitS1 # PSW to handle ext int, 64 bit
#endif
.LwaitpswS1: .LwaitpswS1:
.long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int .long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
.LtimeS1: .LtimeS1:
...@@ -250,6 +264,13 @@ _sclp_print: ...@@ -250,6 +264,13 @@ _sclp_print:
_sclp_print_early: _sclp_print_early:
stm %r6,%r15,24(%r15) # save registers stm %r6,%r15,24(%r15) # save registers
ahi %r15,-96 # create stack frame ahi %r15,-96 # create stack frame
#ifdef CONFIG_64BIT
tm LC_AR_MODE_ID,1
jno .Lesa2
ahi %r15,-80
stmh %r6,%r15,96(%r15) # store upper register halves
.Lesa2:
#endif
lr %r10,%r2 # save string pointer lr %r10,%r2 # save string pointer
lhi %r2,0 lhi %r2,0
bras %r14,_sclp_setup # enable console bras %r14,_sclp_setup # enable console
...@@ -262,6 +283,13 @@ _sclp_print_early: ...@@ -262,6 +283,13 @@ _sclp_print_early:
lhi %r2,1 lhi %r2,1
bras %r14,_sclp_setup # disable console bras %r14,_sclp_setup # disable console
.LendS5: .LendS5:
#ifdef CONFIG_64BIT
tm LC_AR_MODE_ID,1
jno .Lesa3
lmh %r6,%r15,96(%r15) # store upper register halves
ahi %r15,80
.Lesa3:
#endif
lm %r6,%r15,120(%r15) # restore registers lm %r6,%r15,120(%r15) # restore registers
br %r14 br %r14
......
...@@ -396,15 +396,12 @@ static void __init ...@@ -396,15 +396,12 @@ static void __init
setup_lowcore(void) setup_lowcore(void)
{ {
struct _lowcore *lc; struct _lowcore *lc;
int lc_pages;
/* /*
* Setup lowcore for boot cpu * Setup lowcore for boot cpu
*/ */
lc_pages = sizeof(void *) == 8 ? 2 : 1; BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
lc = (struct _lowcore *) lc = __alloc_bootmem(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
__alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0);
memset(lc, 0, lc_pages * PAGE_SIZE);
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
lc->restart_psw.addr = lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler; PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
...@@ -804,7 +801,7 @@ setup_arch(char **cmdline_p) ...@@ -804,7 +801,7 @@ setup_arch(char **cmdline_p)
if (MACHINE_IS_VM) if (MACHINE_IS_VM)
pr_info("Linux is running as a z/VM " pr_info("Linux is running as a z/VM "
"guest operating system in 31-bit mode\n"); "guest operating system in 31-bit mode\n");
else else if (MACHINE_IS_LPAR)
pr_info("Linux is running natively in 31-bit mode\n"); pr_info("Linux is running natively in 31-bit mode\n");
if (MACHINE_HAS_IEEE) if (MACHINE_HAS_IEEE)
pr_info("The hardware system has IEEE compatible " pr_info("The hardware system has IEEE compatible "
...@@ -818,7 +815,7 @@ setup_arch(char **cmdline_p) ...@@ -818,7 +815,7 @@ setup_arch(char **cmdline_p)
"guest operating system in 64-bit mode\n"); "guest operating system in 64-bit mode\n");
else if (MACHINE_IS_KVM) else if (MACHINE_IS_KVM)
pr_info("Linux is running under KVM in 64-bit mode\n"); pr_info("Linux is running under KVM in 64-bit mode\n");
else else if (MACHINE_IS_LPAR)
pr_info("Linux is running natively in 64-bit mode\n"); pr_info("Linux is running natively in 64-bit mode\n");
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h> #include <asm/ipl.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/sigp.h> #include <asm/sigp.h>
...@@ -53,7 +54,7 @@ ...@@ -53,7 +54,7 @@
#include "entry.h" #include "entry.h"
/* logical cpu to cpu address */ /* logical cpu to cpu address */
int __cpu_logical_map[NR_CPUS]; unsigned short __cpu_logical_map[NR_CPUS];
static struct task_struct *current_set[NR_CPUS]; static struct task_struct *current_set[NR_CPUS];
...@@ -72,13 +73,13 @@ static int cpu_management; ...@@ -72,13 +73,13 @@ static int cpu_management;
static DEFINE_PER_CPU(struct cpu, cpu_devices); static DEFINE_PER_CPU(struct cpu, cpu_devices);
static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall(int, int);
static int cpu_stopped(int cpu) static int raw_cpu_stopped(int cpu)
{ {
__u32 status; u32 status;
switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) { switch (raw_sigp_ps(&status, 0, cpu, sigp_sense)) {
case sigp_status_stored: case sigp_status_stored:
/* Check for stopped and check stop state */ /* Check for stopped and check stop state */
if (status & 0x50) if (status & 0x50)
...@@ -90,6 +91,44 @@ static int cpu_stopped(int cpu) ...@@ -90,6 +91,44 @@ static int cpu_stopped(int cpu)
return 0; return 0;
} }
static inline int cpu_stopped(int cpu)
{
return raw_cpu_stopped(cpu_logical_map(cpu));
}
void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
{
struct _lowcore *lc, *current_lc;
struct stack_frame *sf;
struct pt_regs *regs;
unsigned long sp;
if (smp_processor_id() == 0)
func(data);
__load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY);
/* Disable lowcore protection */
__ctl_clear_bit(0, 28);
current_lc = lowcore_ptr[smp_processor_id()];
lc = lowcore_ptr[0];
if (!lc)
lc = current_lc;
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
if (!cpu_online(0))
smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
while (sigp(0, sigp_stop_and_store_status) == sigp_busy)
cpu_relax();
sp = lc->panic_stack;
sp -= sizeof(struct pt_regs);
regs = (struct pt_regs *) sp;
memcpy(&regs->gprs, &current_lc->gpregs_save_area, sizeof(regs->gprs));
regs->psw = lc->psw_save_area;
sp -= STACK_FRAME_OVERHEAD;
sf = (struct stack_frame *) sp;
sf->back_chain = regs->gprs[15];
smp_switch_to_cpu(func, data, sp, stap(), __cpu_logical_map[0]);
}
void smp_send_stop(void) void smp_send_stop(void)
{ {
int cpu, rc; int cpu, rc;
...@@ -103,7 +142,7 @@ void smp_send_stop(void) ...@@ -103,7 +142,7 @@ void smp_send_stop(void)
if (cpu == smp_processor_id()) if (cpu == smp_processor_id())
continue; continue;
do { do {
rc = signal_processor(cpu, sigp_stop); rc = sigp(cpu, sigp_stop);
} while (rc == sigp_busy); } while (rc == sigp_busy);
while (!cpu_stopped(cpu)) while (!cpu_stopped(cpu))
...@@ -139,13 +178,13 @@ static void do_ext_call_interrupt(__u16 code) ...@@ -139,13 +178,13 @@ static void do_ext_call_interrupt(__u16 code)
* Send an external call sigp to another cpu and return without waiting * Send an external call sigp to another cpu and return without waiting
* for its completion. * for its completion.
*/ */
static void smp_ext_bitcall(int cpu, ec_bit_sig sig) static void smp_ext_bitcall(int cpu, int sig)
{ {
/* /*
* Set signaling bit in lowcore of target cpu and kick it * Set signaling bit in lowcore of target cpu and kick it
*/ */
set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy) while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
udelay(10); udelay(10);
} }
...@@ -239,24 +278,8 @@ void smp_ctl_clear_bit(int cr, int bit) ...@@ -239,24 +278,8 @@ void smp_ctl_clear_bit(int cr, int bit)
} }
EXPORT_SYMBOL(smp_ctl_clear_bit); EXPORT_SYMBOL(smp_ctl_clear_bit);
/*
* In early ipl state a temp. logically cpu number is needed, so the sigp
* functions can be used to sense other cpus. Since NR_CPUS is >= 2 on
* CONFIG_SMP and the ipl cpu is logical cpu 0, it must be 1.
*/
#define CPU_INIT_NO 1
#ifdef CONFIG_ZFCPDUMP #ifdef CONFIG_ZFCPDUMP
/*
* zfcpdump_prefix_array holds prefix registers for the following scenario:
* 64 bit zfcpdump kernel and 31 bit kernel which is to be dumped. We have to
* save its prefix registers, since they get lost, when switching from 31 bit
* to 64 bit.
*/
unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
__attribute__((__section__(".data")));
static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
{ {
if (ipl_info.type != IPL_TYPE_FCP_DUMP) if (ipl_info.type != IPL_TYPE_FCP_DUMP)
...@@ -266,21 +289,15 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) ...@@ -266,21 +289,15 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
"the dump\n", cpu, NR_CPUS - 1); "the dump\n", cpu, NR_CPUS - 1);
return; return;
} }
zfcpdump_save_areas[cpu] = kmalloc(sizeof(union save_area), GFP_KERNEL); zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL);
__cpu_logical_map[CPU_INIT_NO] = (__u16) phy_cpu; while (raw_sigp(phy_cpu, sigp_stop_and_store_status) == sigp_busy)
while (signal_processor(CPU_INIT_NO, sigp_stop_and_store_status) ==
sigp_busy)
cpu_relax(); cpu_relax();
memcpy(zfcpdump_save_areas[cpu], memcpy(zfcpdump_save_areas[cpu],
(void *)(unsigned long) store_prefix() + SAVE_AREA_BASE, (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
SAVE_AREA_SIZE); sizeof(struct save_area));
#ifdef CONFIG_64BIT
/* copy original prefix register */
zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu];
#endif
} }
union save_area *zfcpdump_save_areas[NR_CPUS + 1]; struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
EXPORT_SYMBOL_GPL(zfcpdump_save_areas); EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
#else #else
...@@ -389,8 +406,7 @@ static void __init smp_detect_cpus(void) ...@@ -389,8 +406,7 @@ static void __init smp_detect_cpus(void)
for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) { for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) {
if (cpu == boot_cpu_addr) if (cpu == boot_cpu_addr)
continue; continue;
__cpu_logical_map[CPU_INIT_NO] = cpu; if (!raw_cpu_stopped(cpu))
if (!cpu_stopped(CPU_INIT_NO))
continue; continue;
smp_get_save_area(c_cpus, cpu); smp_get_save_area(c_cpus, cpu);
c_cpus++; c_cpus++;
...@@ -413,8 +429,7 @@ static void __init smp_detect_cpus(void) ...@@ -413,8 +429,7 @@ static void __init smp_detect_cpus(void)
cpu_addr = info->cpu[cpu].address; cpu_addr = info->cpu[cpu].address;
if (cpu_addr == boot_cpu_addr) if (cpu_addr == boot_cpu_addr)
continue; continue;
__cpu_logical_map[CPU_INIT_NO] = cpu_addr; if (!raw_cpu_stopped(cpu_addr)) {
if (!cpu_stopped(CPU_INIT_NO)) {
s_cpus++; s_cpus++;
continue; continue;
} }
...@@ -533,18 +548,18 @@ static void smp_free_lowcore(int cpu) ...@@ -533,18 +548,18 @@ static void smp_free_lowcore(int cpu)
/* Upping and downing of CPUs */ /* Upping and downing of CPUs */
int __cpuinit __cpu_up(unsigned int cpu) int __cpuinit __cpu_up(unsigned int cpu)
{ {
struct task_struct *idle;
struct _lowcore *cpu_lowcore; struct _lowcore *cpu_lowcore;
struct task_struct *idle;
struct stack_frame *sf; struct stack_frame *sf;
sigp_ccode ccode;
u32 lowcore; u32 lowcore;
int ccode;
if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
return -EIO; return -EIO;
if (smp_alloc_lowcore(cpu)) if (smp_alloc_lowcore(cpu))
return -ENOMEM; return -ENOMEM;
do { do {
ccode = signal_processor(cpu, sigp_initial_cpu_reset); ccode = sigp(cpu, sigp_initial_cpu_reset);
if (ccode == sigp_busy) if (ccode == sigp_busy)
udelay(10); udelay(10);
if (ccode == sigp_not_operational) if (ccode == sigp_not_operational)
...@@ -552,7 +567,7 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -552,7 +567,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
} while (ccode == sigp_busy); } while (ccode == sigp_busy);
lowcore = (u32)(unsigned long)lowcore_ptr[cpu]; lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
udelay(10); udelay(10);
idle = current_set[cpu]; idle = current_set[cpu];
...@@ -578,7 +593,7 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -578,7 +593,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
eieio(); eieio();
while (signal_processor(cpu, sigp_restart) == sigp_busy) while (sigp(cpu, sigp_restart) == sigp_busy)
udelay(10); udelay(10);
while (!cpu_online(cpu)) while (!cpu_online(cpu))
...@@ -640,7 +655,7 @@ void __cpu_die(unsigned int cpu) ...@@ -640,7 +655,7 @@ void __cpu_die(unsigned int cpu)
/* Wait until target cpu is down */ /* Wait until target cpu is down */
while (!cpu_stopped(cpu)) while (!cpu_stopped(cpu))
cpu_relax(); cpu_relax();
while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy) while (sigp_p(0, cpu, sigp_set_prefix) == sigp_busy)
udelay(10); udelay(10);
smp_free_lowcore(cpu); smp_free_lowcore(cpu);
pr_info("Processor %d stopped\n", cpu); pr_info("Processor %d stopped\n", cpu);
...@@ -649,7 +664,7 @@ void __cpu_die(unsigned int cpu) ...@@ -649,7 +664,7 @@ void __cpu_die(unsigned int cpu)
void cpu_die(void) void cpu_die(void)
{ {
idle_task_exit(); idle_task_exit();
while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
cpu_relax(); cpu_relax();
for (;;); for (;;);
} }
...@@ -765,7 +780,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev, ...@@ -765,7 +780,8 @@ static ssize_t cpu_configure_store(struct sys_device *dev,
get_online_cpus(); get_online_cpus();
mutex_lock(&smp_cpu_state_mutex); mutex_lock(&smp_cpu_state_mutex);
rc = -EBUSY; rc = -EBUSY;
if (cpu_online(cpu)) /* disallow configuration changes of online cpus and cpu 0 */
if (cpu_online(cpu) || cpu == 0)
goto out; goto out;
rc = 0; rc = 0;
switch (val) { switch (val) {
......
/*
* 31-bit switch cpu code
*
* Copyright IBM Corp. 2009
*
*/
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
# smp_switch_to_cpu switches to destination cpu and executes the passed function
# Parameter: %r2 - function to call
# %r3 - function parameter
# %r4 - stack poiner
# %r5 - current cpu
# %r6 - destination cpu
.section .text
.align 4
.globl smp_switch_to_cpu
smp_switch_to_cpu:
stm %r6,%r15,__SF_GPRS(%r15)
lr %r1,%r15
ahi %r15,-STACK_FRAME_OVERHEAD
st %r1,__SF_BACKCHAIN(%r15)
basr %r13,0
0: la %r1,.gprregs_addr-0b(%r13)
l %r1,0(%r1)
stm %r0,%r15,0(%r1)
1: sigp %r0,%r6,__SIGP_RESTART /* start destination CPU */
brc 2,1b /* busy, try again */
2: sigp %r0,%r5,__SIGP_STOP /* stop current CPU */
brc 2,2b /* busy, try again */
3: j 3b
.globl smp_restart_cpu
smp_restart_cpu:
basr %r13,0
0: la %r1,.gprregs_addr-0b(%r13)
l %r1,0(%r1)
lm %r0,%r15,0(%r1)
1: sigp %r0,%r5,__SIGP_SENSE /* Wait for calling CPU */
brc 10,1b /* busy, accepted (status 0), running */
tmll %r0,0x40 /* Test if calling CPU is stopped */
jz 1b
ltr %r4,%r4 /* New stack ? */
jz 1f
lr %r15,%r4
1: basr %r14,%r2
.gprregs_addr:
.long .gprregs
.section .data,"aw",@progbits
.gprregs:
.rept 16
.long 0
.endr
/*
* 64-bit switch cpu code
*
* Copyright IBM Corp. 2009
*
*/
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
# smp_switch_to_cpu switches to destination cpu and executes the passed function
# Parameter: %r2 - function to call
# %r3 - function parameter
# %r4 - stack poiner
# %r5 - current cpu
# %r6 - destination cpu
.section .text
.align 4
.globl smp_switch_to_cpu
smp_switch_to_cpu:
stmg %r6,%r15,__SF_GPRS(%r15)
lgr %r1,%r15
aghi %r15,-STACK_FRAME_OVERHEAD
stg %r1,__SF_BACKCHAIN(%r15)
larl %r1,.gprregs
stmg %r0,%r15,0(%r1)
1: sigp %r0,%r6,__SIGP_RESTART /* start destination CPU */
brc 2,1b /* busy, try again */
2: sigp %r0,%r5,__SIGP_STOP /* stop current CPU */
brc 2,2b /* busy, try again */
3: j 3b
.globl smp_restart_cpu
smp_restart_cpu:
larl %r1,.gprregs
lmg %r0,%r15,0(%r1)
1: sigp %r0,%r5,__SIGP_SENSE /* Wait for calling CPU */
brc 10,1b /* busy, accepted (status 0), running */
tmll %r0,0x40 /* Test if calling CPU is stopped */
jz 1b
ltgr %r4,%r4 /* New stack ? */
jz 1f
lgr %r15,%r4
1: basr %r14,%r2
.section .data,"aw",@progbits
.gprregs:
.rept 16
.quad 0
.endr
...@@ -176,7 +176,7 @@ pgm_check_entry: ...@@ -176,7 +176,7 @@ pgm_check_entry:
cgr %r1,%r2 cgr %r1,%r2
je restore_registers /* r1 = r2 -> nothing to do */ je restore_registers /* r1 = r2 -> nothing to do */
larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */ larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */
mvc __LC_RESTART_PSW(16,%r0),0(%r4) mvc __LC_RST_NEW_PSW(16,%r0),0(%r4)
3: 3:
sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET
brc 8,4f /* accepted */ brc 8,4f /* accepted */
......
...@@ -51,14 +51,6 @@ ...@@ -51,14 +51,6 @@
#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
/*
* Create a small time difference between the timer interrupts
* on the different cpus to avoid lock contention.
*/
#define CPU_DEVIATION (smp_processor_id() << 12)
#define TICK_SIZE tick
u64 sched_clock_base_cc = -1; /* Force to data section. */ u64 sched_clock_base_cc = -1; /* Force to data section. */
EXPORT_SYMBOL_GPL(sched_clock_base_cc); EXPORT_SYMBOL_GPL(sched_clock_base_cc);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <asm/asm-offsets.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -39,7 +39,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu) ...@@ -39,7 +39,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
vcpu->run->s390_reset_flags = 0; vcpu->run->s390_reset_flags = 0;
break; break;
default: default:
return -ENOTSUPP; return -EOPNOTSUPP;
} }
atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
...@@ -62,6 +62,6 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) ...@@ -62,6 +62,6 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
case 0x308: case 0x308:
return __diag_ipl_functions(vcpu); return __diag_ipl_functions(vcpu);
default: default:
return -ENOTSUPP; return -EOPNOTSUPP;
} }
} }
...@@ -32,7 +32,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu) ...@@ -32,7 +32,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
vcpu->stat.instruction_lctlg++; vcpu->stat.instruction_lctlg++;
if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f) if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
return -ENOTSUPP; return -EOPNOTSUPP;
useraddr = disp2; useraddr = disp2;
if (base2) if (base2)
...@@ -138,7 +138,7 @@ static int handle_stop(struct kvm_vcpu *vcpu) ...@@ -138,7 +138,7 @@ static int handle_stop(struct kvm_vcpu *vcpu)
rc = __kvm_s390_vcpu_store_status(vcpu, rc = __kvm_s390_vcpu_store_status(vcpu,
KVM_S390_STORE_STATUS_NOADDR); KVM_S390_STORE_STATUS_NOADDR);
if (rc >= 0) if (rc >= 0)
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
} }
if (vcpu->arch.local_int.action_bits & ACTION_RELOADVCPU_ON_STOP) { if (vcpu->arch.local_int.action_bits & ACTION_RELOADVCPU_ON_STOP) {
...@@ -150,7 +150,7 @@ static int handle_stop(struct kvm_vcpu *vcpu) ...@@ -150,7 +150,7 @@ static int handle_stop(struct kvm_vcpu *vcpu)
if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) { if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP; vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
VCPU_EVENT(vcpu, 3, "%s", "cpu stopped"); VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
} }
spin_unlock_bh(&vcpu->arch.local_int.lock); spin_unlock_bh(&vcpu->arch.local_int.lock);
...@@ -171,9 +171,9 @@ static int handle_validity(struct kvm_vcpu *vcpu) ...@@ -171,9 +171,9 @@ static int handle_validity(struct kvm_vcpu *vcpu)
2*PAGE_SIZE); 2*PAGE_SIZE);
if (rc) if (rc)
/* user will receive sigsegv, exit to user */ /* user will receive sigsegv, exit to user */
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
} else } else
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
if (rc) if (rc)
VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d", VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
...@@ -189,7 +189,7 @@ static int handle_instruction(struct kvm_vcpu *vcpu) ...@@ -189,7 +189,7 @@ static int handle_instruction(struct kvm_vcpu *vcpu)
handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8]; handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
if (handler) if (handler)
return handler(vcpu); return handler(vcpu);
return -ENOTSUPP; return -EOPNOTSUPP;
} }
static int handle_prog(struct kvm_vcpu *vcpu) static int handle_prog(struct kvm_vcpu *vcpu)
...@@ -206,7 +206,7 @@ static int handle_instruction_and_prog(struct kvm_vcpu *vcpu) ...@@ -206,7 +206,7 @@ static int handle_instruction_and_prog(struct kvm_vcpu *vcpu)
rc = handle_instruction(vcpu); rc = handle_instruction(vcpu);
rc2 = handle_prog(vcpu); rc2 = handle_prog(vcpu);
if (rc == -ENOTSUPP) if (rc == -EOPNOTSUPP)
vcpu->arch.sie_block->icptcode = 0x04; vcpu->arch.sie_block->icptcode = 0x04;
if (rc) if (rc)
return rc; return rc;
...@@ -231,9 +231,9 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) ...@@ -231,9 +231,9 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
u8 code = vcpu->arch.sie_block->icptcode; u8 code = vcpu->arch.sie_block->icptcode;
if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs)) if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs))
return -ENOTSUPP; return -EOPNOTSUPP;
func = intercept_funcs[code >> 2]; func = intercept_funcs[code >> 2];
if (func) if (func)
return func(vcpu); return func(vcpu);
return -ENOTSUPP; return -EOPNOTSUPP;
} }
...@@ -10,12 +10,12 @@ ...@@ -10,12 +10,12 @@
* Author(s): Carsten Otte <cotte@de.ibm.com> * Author(s): Carsten Otte <cotte@de.ibm.com>
*/ */
#include <asm/lowcore.h>
#include <asm/uaccess.h>
#include <linux/hrtimer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kvm_host.h> #include <linux/kvm_host.h>
#include <linux/hrtimer.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <asm/asm-offsets.h>
#include <asm/uaccess.h>
#include "kvm-s390.h" #include "kvm-s390.h"
#include "gaccess.h" #include "gaccess.h"
...@@ -187,8 +187,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, ...@@ -187,8 +187,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
if (rc == -EFAULT) if (rc == -EFAULT)
exception = 1; exception = 1;
rc = put_guest_u64(vcpu, __LC_PFAULT_INTPARM, rc = put_guest_u64(vcpu, __LC_EXT_PARAMS2,
inti->ext.ext_params2); inti->ext.ext_params2);
if (rc == -EFAULT) if (rc == -EFAULT)
exception = 1; exception = 1;
break; break;
...@@ -342,7 +342,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) ...@@ -342,7 +342,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
if (psw_interrupts_disabled(vcpu)) { if (psw_interrupts_disabled(vcpu)) {
VCPU_EVENT(vcpu, 3, "%s", "disabled wait"); VCPU_EVENT(vcpu, 3, "%s", "disabled wait");
__unset_cpu_idle(vcpu); __unset_cpu_idle(vcpu);
return -ENOTSUPP; /* disabled wait */ return -EOPNOTSUPP; /* disabled wait */
} }
if (psw_extint_disabled(vcpu) || if (psw_extint_disabled(vcpu) ||
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/asm-offsets.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/nmi.h> #include <asm/nmi.h>
...@@ -543,7 +544,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ...@@ -543,7 +544,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
rc = -EINTR; rc = -EINTR;
} }
if (rc == -ENOTSUPP) { if (rc == -EOPNOTSUPP) {
/* intercept cannot be handled in-kernel, prepare kvm-run */ /* intercept cannot be handled in-kernel, prepare kvm-run */
kvm_run->exit_reason = KVM_EXIT_S390_SIEIC; kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode; kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
...@@ -603,45 +604,45 @@ int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) ...@@ -603,45 +604,45 @@ int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
} else } else
prefix = 0; prefix = 0;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, fp_regs), if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
vcpu->arch.guest_fpregs.fprs, 128, prefix)) vcpu->arch.guest_fpregs.fprs, 128, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, gp_regs), if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
vcpu->arch.guest_gprs, 128, prefix)) vcpu->arch.guest_gprs, 128, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, psw), if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
&vcpu->arch.sie_block->gpsw, 16, prefix)) &vcpu->arch.sie_block->gpsw, 16, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, pref_reg), if (__guestcopy(vcpu, addr + offsetof(struct save_area, pref_reg),
&vcpu->arch.sie_block->prefix, 4, prefix)) &vcpu->arch.sie_block->prefix, 4, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, if (__guestcopy(vcpu,
addr + offsetof(struct save_area_s390x, fp_ctrl_reg), addr + offsetof(struct save_area, fp_ctrl_reg),
&vcpu->arch.guest_fpregs.fpc, 4, prefix)) &vcpu->arch.guest_fpregs.fpc, 4, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, tod_reg), if (__guestcopy(vcpu, addr + offsetof(struct save_area, tod_reg),
&vcpu->arch.sie_block->todpr, 4, prefix)) &vcpu->arch.sie_block->todpr, 4, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, timer), if (__guestcopy(vcpu, addr + offsetof(struct save_area, timer),
&vcpu->arch.sie_block->cputm, 8, prefix)) &vcpu->arch.sie_block->cputm, 8, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, clk_cmp), if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp),
&vcpu->arch.sie_block->ckc, 8, prefix)) &vcpu->arch.sie_block->ckc, 8, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, acc_regs), if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
&vcpu->arch.guest_acrs, 64, prefix)) &vcpu->arch.guest_acrs, 64, prefix))
return -EFAULT; return -EFAULT;
if (__guestcopy(vcpu, if (__guestcopy(vcpu,
addr + offsetof(struct save_area_s390x, ctrl_regs), addr + offsetof(struct save_area, ctrl_regs),
&vcpu->arch.sie_block->gcr, 128, prefix)) &vcpu->arch.sie_block->gcr, 128, prefix))
return -EFAULT; return -EFAULT;
return 0; return 0;
......
...@@ -323,5 +323,5 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) ...@@ -323,5 +323,5 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
else else
return handler(vcpu); return handler(vcpu);
} }
return -ENOTSUPP; return -EOPNOTSUPP;
} }
...@@ -172,7 +172,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) ...@@ -172,7 +172,7 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter)
rc = 0; /* order accepted */ rc = 0; /* order accepted */
break; break;
default: default:
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
} }
return rc; return rc;
} }
...@@ -293,7 +293,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) ...@@ -293,7 +293,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
vcpu->stat.instruction_sigp_restart++; vcpu->stat.instruction_sigp_restart++;
/* user space must know about restart */ /* user space must know about restart */
default: default:
return -ENOTSUPP; return -EOPNOTSUPP;
} }
if (rc < 0) if (rc < 0)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for s390-specific library files.. # Makefile for s390-specific library files..
# #
lib-y += delay.o string.o uaccess_std.o uaccess_pt.o lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o lib-$(CONFIG_SMP) += spinlock.o
...@@ -43,16 +43,24 @@ void arch_spin_lock_wait(arch_spinlock_t *lp) ...@@ -43,16 +43,24 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
{ {
int count = spin_retry; int count = spin_retry;
unsigned int cpu = ~smp_processor_id(); unsigned int cpu = ~smp_processor_id();
unsigned int owner;
while (1) { while (1) {
if (count-- <= 0) { owner = lp->owner_cpu;
unsigned int owner = lp->owner_cpu; if (!owner || smp_vcpu_scheduled(~owner)) {
if (owner != 0) for (count = spin_retry; count > 0; count--) {
_raw_yield_cpu(~owner); if (arch_spin_is_locked(lp))
count = spin_retry; continue;
if (_raw_compare_and_swap(&lp->owner_cpu, 0,
cpu) == 0)
return;
}
if (MACHINE_IS_LPAR)
continue;
} }
if (arch_spin_is_locked(lp)) owner = lp->owner_cpu;
continue; if (owner)
_raw_yield_cpu(~owner);
if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
return; return;
} }
...@@ -63,17 +71,27 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags) ...@@ -63,17 +71,27 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
{ {
int count = spin_retry; int count = spin_retry;
unsigned int cpu = ~smp_processor_id(); unsigned int cpu = ~smp_processor_id();
unsigned int owner;
local_irq_restore(flags); local_irq_restore(flags);
while (1) { while (1) {
if (count-- <= 0) { owner = lp->owner_cpu;
unsigned int owner = lp->owner_cpu; if (!owner || smp_vcpu_scheduled(~owner)) {
if (owner != 0) for (count = spin_retry; count > 0; count--) {
_raw_yield_cpu(~owner); if (arch_spin_is_locked(lp))
count = spin_retry; continue;
local_irq_disable();
if (_raw_compare_and_swap(&lp->owner_cpu, 0,
cpu) == 0)
return;
local_irq_restore(flags);
}
if (MACHINE_IS_LPAR)
continue;
} }
if (arch_spin_is_locked(lp)) owner = lp->owner_cpu;
continue; if (owner)
_raw_yield_cpu(~owner);
local_irq_disable(); local_irq_disable();
if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0)
return; return;
...@@ -100,8 +118,11 @@ EXPORT_SYMBOL(arch_spin_trylock_retry); ...@@ -100,8 +118,11 @@ EXPORT_SYMBOL(arch_spin_trylock_retry);
void arch_spin_relax(arch_spinlock_t *lock) void arch_spin_relax(arch_spinlock_t *lock)
{ {
unsigned int cpu = lock->owner_cpu; unsigned int cpu = lock->owner_cpu;
if (cpu != 0) if (cpu != 0) {
_raw_yield_cpu(~cpu); if (MACHINE_IS_VM || MACHINE_IS_KVM ||
!smp_vcpu_scheduled(~cpu))
_raw_yield_cpu(~cpu);
}
} }
EXPORT_SYMBOL(arch_spin_relax); EXPORT_SYMBOL(arch_spin_relax);
......
#include <linux/module.h>
#include <linux/bug.h>
void copy_from_user_overflow(void)
{
WARN(1, "Buffer overflow detected!\n");
}
EXPORT_SYMBOL(copy_from_user_overflow);
...@@ -309,7 +309,7 @@ query_segment_type (struct dcss_segment *seg) ...@@ -309,7 +309,7 @@ query_segment_type (struct dcss_segment *seg)
} }
#endif #endif
if (qout->segcnt > 6) { if (qout->segcnt > 6) {
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
goto out_free; goto out_free;
} }
...@@ -324,11 +324,11 @@ query_segment_type (struct dcss_segment *seg) ...@@ -324,11 +324,11 @@ query_segment_type (struct dcss_segment *seg)
for (i=0; i<qout->segcnt; i++) { for (i=0; i<qout->segcnt; i++) {
if (((qout->range[i].start & 0xff) != SEG_TYPE_EW) && if (((qout->range[i].start & 0xff) != SEG_TYPE_EW) &&
((qout->range[i].start & 0xff) != SEG_TYPE_EN)) { ((qout->range[i].start & 0xff) != SEG_TYPE_EN)) {
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
goto out_free; goto out_free;
} }
if (start != qout->range[i].start >> PAGE_SHIFT) { if (start != qout->range[i].start >> PAGE_SHIFT) {
rc = -ENOTSUPP; rc = -EOPNOTSUPP;
goto out_free; goto out_free;
} }
start = (qout->range[i].end >> PAGE_SHIFT) + 1; start = (qout->range[i].end >> PAGE_SHIFT) + 1;
...@@ -357,7 +357,7 @@ query_segment_type (struct dcss_segment *seg) ...@@ -357,7 +357,7 @@ query_segment_type (struct dcss_segment *seg)
* -ENOSYS : we are not running on VM * -ENOSYS : we are not running on VM
* -EIO : could not perform query diagnose * -EIO : could not perform query diagnose
* -ENOENT : no such segment * -ENOENT : no such segment
* -ENOTSUPP: multi-part segment cannot be used with linux * -EOPNOTSUPP: multi-part segment cannot be used with linux
* -ENOMEM : out of memory * -ENOMEM : out of memory
* 0 .. 6 : type of segment as defined in include/asm-s390/extmem.h * 0 .. 6 : type of segment as defined in include/asm-s390/extmem.h
*/ */
...@@ -515,7 +515,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long ...@@ -515,7 +515,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
* -ENOSYS : we are not running on VM * -ENOSYS : we are not running on VM
* -EIO : could not perform query or load diagnose * -EIO : could not perform query or load diagnose
* -ENOENT : no such segment * -ENOENT : no such segment
* -ENOTSUPP: multi-part segment cannot be used with linux * -EOPNOTSUPP: multi-part segment cannot be used with linux
* -ENOSPC : segment cannot be used (overlaps with storage) * -ENOSPC : segment cannot be used (overlaps with storage)
* -EBUSY : segment can temporarily not be used (overlaps with dcss) * -EBUSY : segment can temporarily not be used (overlaps with dcss)
* -ERANGE : segment cannot be used (exceeds kernel mapping range) * -ERANGE : segment cannot be used (exceeds kernel mapping range)
...@@ -742,7 +742,7 @@ void segment_warning(int rc, char *seg_name) ...@@ -742,7 +742,7 @@ void segment_warning(int rc, char *seg_name)
pr_err("Loading or querying DCSS %s resulted in a " pr_err("Loading or querying DCSS %s resulted in a "
"hardware error\n", seg_name); "hardware error\n", seg_name);
break; break;
case -ENOTSUPP: case -EOPNOTSUPP:
pr_err("DCSS %s has multiple page ranges and cannot be " pr_err("DCSS %s has multiple page ranges and cannot be "
"loaded or queried\n", seg_name); "loaded or queried\n", seg_name);
break; break;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <asm/asm-offsets.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
...@@ -59,15 +60,13 @@ static inline int notify_page_fault(struct pt_regs *regs) ...@@ -59,15 +60,13 @@ static inline int notify_page_fault(struct pt_regs *regs)
{ {
int ret = 0; int ret = 0;
#ifdef CONFIG_KPROBES
/* kprobe_running() needs smp_processor_id() */ /* kprobe_running() needs smp_processor_id() */
if (!user_mode(regs)) { if (kprobes_built_in() && !user_mode(regs)) {
preempt_disable(); preempt_disable();
if (kprobe_running() && kprobe_fault_handler(regs, 14)) if (kprobe_running() && kprobe_fault_handler(regs, 14))
ret = 1; ret = 1;
preempt_enable(); preempt_enable();
} }
#endif
return ret; return ret;
} }
......
...@@ -143,33 +143,34 @@ void kernel_map_pages(struct page *page, int numpages, int enable) ...@@ -143,33 +143,34 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
} }
#endif #endif
void free_initmem(void) void free_init_pages(char *what, unsigned long begin, unsigned long end)
{ {
unsigned long addr; unsigned long addr = begin;
addr = (unsigned long)(&__init_begin); if (begin >= end)
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { return;
for (; addr < end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr)); ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr)); init_page_count(virt_to_page(addr));
memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); memset((void *)(addr & PAGE_MASK), POISON_FREE_INITMEM,
PAGE_SIZE);
free_page(addr); free_page(addr);
totalram_pages++; totalram_pages++;
} }
printk ("Freeing unused kernel memory: %ldk freed\n", printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10); }
void free_initmem(void)
{
free_init_pages("unused kernel memory",
(unsigned long)&__init_begin,
(unsigned long)&__init_end);
} }
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end) void free_initrd_mem(unsigned long start, unsigned long end)
{ {
if (start < end) free_init_pages("initrd memory", start, end);
printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
ClearPageReserved(virt_to_page(start));
init_page_count(virt_to_page(start));
free_page(start);
totalram_pages++;
}
} }
#endif #endif
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/async.h> #include <linux/async.h>
#include <linux/mutex.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
...@@ -112,6 +113,7 @@ struct dasd_device *dasd_alloc_device(void) ...@@ -112,6 +113,7 @@ struct dasd_device *dasd_alloc_device(void)
INIT_WORK(&device->restore_device, do_restore_device); INIT_WORK(&device->restore_device, do_restore_device);
device->state = DASD_STATE_NEW; device->state = DASD_STATE_NEW;
device->target = DASD_STATE_NEW; device->target = DASD_STATE_NEW;
mutex_init(&device->state_mutex);
return device; return device;
} }
...@@ -321,8 +323,8 @@ static int dasd_state_ready_to_basic(struct dasd_device *device) ...@@ -321,8 +323,8 @@ static int dasd_state_ready_to_basic(struct dasd_device *device)
device->state = DASD_STATE_READY; device->state = DASD_STATE_READY;
return rc; return rc;
} }
dasd_destroy_partitions(block);
dasd_flush_request_queue(block); dasd_flush_request_queue(block);
dasd_destroy_partitions(block);
block->blocks = 0; block->blocks = 0;
block->bp_block = 0; block->bp_block = 0;
block->s2b_shift = 0; block->s2b_shift = 0;
...@@ -484,10 +486,8 @@ static void dasd_change_state(struct dasd_device *device) ...@@ -484,10 +486,8 @@ static void dasd_change_state(struct dasd_device *device)
if (rc) if (rc)
device->target = device->state; device->target = device->state;
if (device->state == device->target) { if (device->state == device->target)
wake_up(&dasd_init_waitq); wake_up(&dasd_init_waitq);
dasd_put_device(device);
}
/* let user-space know that the device status changed */ /* let user-space know that the device status changed */
kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);
...@@ -502,7 +502,9 @@ static void dasd_change_state(struct dasd_device *device) ...@@ -502,7 +502,9 @@ static void dasd_change_state(struct dasd_device *device)
static void do_kick_device(struct work_struct *work) static void do_kick_device(struct work_struct *work)
{ {
struct dasd_device *device = container_of(work, struct dasd_device, kick_work); struct dasd_device *device = container_of(work, struct dasd_device, kick_work);
mutex_lock(&device->state_mutex);
dasd_change_state(device); dasd_change_state(device);
mutex_unlock(&device->state_mutex);
dasd_schedule_device_bh(device); dasd_schedule_device_bh(device);
dasd_put_device(device); dasd_put_device(device);
} }
...@@ -539,18 +541,19 @@ void dasd_restore_device(struct dasd_device *device) ...@@ -539,18 +541,19 @@ void dasd_restore_device(struct dasd_device *device)
void dasd_set_target_state(struct dasd_device *device, int target) void dasd_set_target_state(struct dasd_device *device, int target)
{ {
dasd_get_device(device); dasd_get_device(device);
mutex_lock(&device->state_mutex);
/* If we are in probeonly mode stop at DASD_STATE_READY. */ /* If we are in probeonly mode stop at DASD_STATE_READY. */
if (dasd_probeonly && target > DASD_STATE_READY) if (dasd_probeonly && target > DASD_STATE_READY)
target = DASD_STATE_READY; target = DASD_STATE_READY;
if (device->target != target) { if (device->target != target) {
if (device->state == target) { if (device->state == target)
wake_up(&dasd_init_waitq); wake_up(&dasd_init_waitq);
dasd_put_device(device);
}
device->target = target; device->target = target;
} }
if (device->state != device->target) if (device->state != device->target)
dasd_change_state(device); dasd_change_state(device);
mutex_unlock(&device->state_mutex);
dasd_put_device(device);
} }
/* /*
...@@ -1000,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, ...@@ -1000,12 +1003,20 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
return; return;
} }
device = (struct dasd_device *) cqr->startdev; device = dasd_device_from_cdev_locked(cdev);
if (device == NULL || if (IS_ERR(device)) {
device != dasd_device_from_cdev_locked(cdev) || DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { "unable to get device from cdev");
return;
}
if (!cqr->startdev ||
device != cqr->startdev ||
strncmp(cqr->startdev->discipline->ebcname,
(char *) &cqr->magic, 4)) {
DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s", DBF_EVENT_DEVID(DBF_DEBUG, cdev, "%s",
"invalid device in request"); "invalid device in request");
dasd_put_device(device);
return; return;
} }
...@@ -1692,7 +1703,6 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr) ...@@ -1692,7 +1703,6 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr)
cqr, rc); cqr, rc);
} else { } else {
cqr->stopclk = get_clock(); cqr->stopclk = get_clock();
rc = 1;
} }
break; break;
default: /* already finished or clear pending - do nothing */ default: /* already finished or clear pending - do nothing */
...@@ -2170,9 +2180,13 @@ static void dasd_flush_request_queue(struct dasd_block *block) ...@@ -2170,9 +2180,13 @@ static void dasd_flush_request_queue(struct dasd_block *block)
static int dasd_open(struct block_device *bdev, fmode_t mode) static int dasd_open(struct block_device *bdev, fmode_t mode)
{ {
struct dasd_block *block = bdev->bd_disk->private_data; struct dasd_block *block = bdev->bd_disk->private_data;
struct dasd_device *base = block->base; struct dasd_device *base;
int rc; int rc;
if (!block)
return -ENODEV;
base = block->base;
atomic_inc(&block->open_count); atomic_inc(&block->open_count);
if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
rc = -ENODEV; rc = -ENODEV;
...@@ -2285,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie) ...@@ -2285,11 +2299,6 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
if (ret) if (ret)
pr_warning("%s: Setting the DASD online failed with rc=%d\n", pr_warning("%s: Setting the DASD online failed with rc=%d\n",
dev_name(&cdev->dev), ret); dev_name(&cdev->dev), ret);
else {
struct dasd_device *device = dasd_device_from_cdev(cdev);
wait_event(dasd_init_waitq, _wait_for_device(device));
dasd_put_device(device);
}
} }
/* /*
...@@ -2424,6 +2433,9 @@ int dasd_generic_set_online(struct ccw_device *cdev, ...@@ -2424,6 +2433,9 @@ int dasd_generic_set_online(struct ccw_device *cdev,
} else } else
pr_debug("dasd_generic device %s found\n", pr_debug("dasd_generic device %s found\n",
dev_name(&cdev->dev)); dev_name(&cdev->dev));
wait_event(dasd_init_waitq, _wait_for_device(device));
dasd_put_device(device); dasd_put_device(device);
return rc; return rc;
} }
......
...@@ -874,12 +874,19 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr, ...@@ -874,12 +874,19 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr,
ssize_t len; ssize_t len;
device = dasd_device_from_cdev(to_ccwdev(dev)); device = dasd_device_from_cdev(to_ccwdev(dev));
if (!IS_ERR(device) && device->discipline) { if (IS_ERR(device))
goto out;
else if (!device->discipline) {
dasd_put_device(device);
goto out;
} else {
len = snprintf(buf, PAGE_SIZE, "%s\n", len = snprintf(buf, PAGE_SIZE, "%s\n",
device->discipline->name); device->discipline->name);
dasd_put_device(device); dasd_put_device(device);
} else return len;
len = snprintf(buf, PAGE_SIZE, "none\n"); }
out:
len = snprintf(buf, PAGE_SIZE, "none\n");
return len; return len;
} }
......
...@@ -88,6 +88,7 @@ void dasd_gendisk_free(struct dasd_block *block) ...@@ -88,6 +88,7 @@ void dasd_gendisk_free(struct dasd_block *block)
if (block->gdp) { if (block->gdp) {
del_gendisk(block->gdp); del_gendisk(block->gdp);
block->gdp->queue = NULL; block->gdp->queue = NULL;
block->gdp->private_data = NULL;
put_disk(block->gdp); put_disk(block->gdp);
block->gdp = NULL; block->gdp = NULL;
} }
......
...@@ -368,6 +368,7 @@ struct dasd_device { ...@@ -368,6 +368,7 @@ struct dasd_device {
/* Device state and target state. */ /* Device state and target state. */
int state, target; int state, target;
struct mutex state_mutex;
int stopped; /* device (ccw_device_start) was stopped */ int stopped; /* device (ccw_device_start) was stopped */
/* reference count. */ /* reference count. */
......
...@@ -165,51 +165,32 @@ static const struct file_operations dasd_devices_file_ops = { ...@@ -165,51 +165,32 @@ static const struct file_operations dasd_devices_file_ops = {
.release = seq_release, .release = seq_release,
}; };
static int
dasd_calc_metrics(char *page, char **start, off_t off,
int count, int *eof, int len)
{
len = (len > off) ? len - off : 0;
if (len > count)
len = count;
if (len < count)
*eof = 1;
*start = page + off;
return len;
}
#ifdef CONFIG_DASD_PROFILE #ifdef CONFIG_DASD_PROFILE
static char * static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor)
dasd_statistics_array(char *str, unsigned int *array, int factor)
{ {
int i; int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
str += sprintf(str, "%7d ", array[i] / factor); seq_printf(m, "%7d ", array[i] / factor);
if (i == 15) if (i == 15)
str += sprintf(str, "\n"); seq_putc(m, '\n');
} }
str += sprintf(str,"\n"); seq_putc(m, '\n');
return str;
} }
#endif /* CONFIG_DASD_PROFILE */ #endif /* CONFIG_DASD_PROFILE */
static int static int dasd_stats_proc_show(struct seq_file *m, void *v)
dasd_statistics_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{ {
unsigned long len;
#ifdef CONFIG_DASD_PROFILE #ifdef CONFIG_DASD_PROFILE
struct dasd_profile_info_t *prof; struct dasd_profile_info_t *prof;
char *str;
int factor; int factor;
/* check for active profiling */ /* check for active profiling */
if (dasd_profile_level == DASD_PROFILE_OFF) { if (dasd_profile_level == DASD_PROFILE_OFF) {
len = sprintf(page, "Statistics are off - they might be " seq_printf(m, "Statistics are off - they might be "
"switched on using 'echo set on > " "switched on using 'echo set on > "
"/proc/dasd/statistics'\n"); "/proc/dasd/statistics'\n");
return dasd_calc_metrics(page, start, off, count, eof, len); return 0;
} }
prof = &dasd_global_profile; prof = &dasd_global_profile;
...@@ -217,47 +198,49 @@ dasd_statistics_read(char *page, char **start, off_t off, ...@@ -217,47 +198,49 @@ dasd_statistics_read(char *page, char **start, off_t off,
for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
factor *= 10); factor *= 10);
str = page; seq_printf(m, "%d dasd I/O requests\n", prof->dasd_io_reqs);
str += sprintf(str, "%d dasd I/O requests\n", prof->dasd_io_reqs); seq_printf(m, "with %u sectors(512B each)\n",
str += sprintf(str, "with %u sectors(512B each)\n",
prof->dasd_io_sects); prof->dasd_io_sects);
str += sprintf(str, "Scale Factor is %d\n", factor); seq_printf(m, "Scale Factor is %d\n", factor);
str += sprintf(str, seq_printf(m,
" __<4 ___8 __16 __32 __64 _128 " " __<4 ___8 __16 __32 __64 _128 "
" _256 _512 __1k __2k __4k __8k " " _256 _512 __1k __2k __4k __8k "
" _16k _32k _64k 128k\n"); " _16k _32k _64k 128k\n");
str += sprintf(str, seq_printf(m,
" _256 _512 __1M __2M __4M __8M " " _256 _512 __1M __2M __4M __8M "
" _16M _32M _64M 128M 256M 512M " " _16M _32M _64M 128M 256M 512M "
" __1G __2G __4G " " _>4G\n"); " __1G __2G __4G " " _>4G\n");
str += sprintf(str, "Histogram of sizes (512B secs)\n"); seq_printf(m, "Histogram of sizes (512B secs)\n");
str = dasd_statistics_array(str, prof->dasd_io_secs, factor); dasd_statistics_array(m, prof->dasd_io_secs, factor);
str += sprintf(str, "Histogram of I/O times (microseconds)\n"); seq_printf(m, "Histogram of I/O times (microseconds)\n");
str = dasd_statistics_array(str, prof->dasd_io_times, factor); dasd_statistics_array(m, prof->dasd_io_times, factor);
str += sprintf(str, "Histogram of I/O times per sector\n"); seq_printf(m, "Histogram of I/O times per sector\n");
str = dasd_statistics_array(str, prof->dasd_io_timps, factor); dasd_statistics_array(m, prof->dasd_io_timps, factor);
str += sprintf(str, "Histogram of I/O time till ssch\n"); seq_printf(m, "Histogram of I/O time till ssch\n");
str = dasd_statistics_array(str, prof->dasd_io_time1, factor); dasd_statistics_array(m, prof->dasd_io_time1, factor);
str += sprintf(str, "Histogram of I/O time between ssch and irq\n"); seq_printf(m, "Histogram of I/O time between ssch and irq\n");
str = dasd_statistics_array(str, prof->dasd_io_time2, factor); dasd_statistics_array(m, prof->dasd_io_time2, factor);
str += sprintf(str, "Histogram of I/O time between ssch " seq_printf(m, "Histogram of I/O time between ssch "
"and irq per sector\n"); "and irq per sector\n");
str = dasd_statistics_array(str, prof->dasd_io_time2ps, factor); dasd_statistics_array(m, prof->dasd_io_time2ps, factor);
str += sprintf(str, "Histogram of I/O time between irq and end\n"); seq_printf(m, "Histogram of I/O time between irq and end\n");
str = dasd_statistics_array(str, prof->dasd_io_time3, factor); dasd_statistics_array(m, prof->dasd_io_time3, factor);
str += sprintf(str, "# of req in chanq at enqueuing (1..32) \n"); seq_printf(m, "# of req in chanq at enqueuing (1..32) \n");
str = dasd_statistics_array(str, prof->dasd_io_nr_req, factor); dasd_statistics_array(m, prof->dasd_io_nr_req, factor);
len = str - page;
#else #else
len = sprintf(page, "Statistics are not activated in this kernel\n"); seq_printf(m, "Statistics are not activated in this kernel\n");
#endif #endif
return dasd_calc_metrics(page, start, off, count, eof, len); return 0;
} }
static int static int dasd_stats_proc_open(struct inode *inode, struct file *file)
dasd_statistics_write(struct file *file, const char __user *user_buf, {
unsigned long user_len, void *data) return single_open(file, dasd_stats_proc_show, NULL);
}
static ssize_t dasd_stats_proc_write(struct file *file,
const char __user *user_buf, size_t user_len, loff_t *pos)
{ {
#ifdef CONFIG_DASD_PROFILE #ifdef CONFIG_DASD_PROFILE
char *buffer, *str; char *buffer, *str;
...@@ -308,6 +291,15 @@ dasd_statistics_write(struct file *file, const char __user *user_buf, ...@@ -308,6 +291,15 @@ dasd_statistics_write(struct file *file, const char __user *user_buf,
#endif /* CONFIG_DASD_PROFILE */ #endif /* CONFIG_DASD_PROFILE */
} }
static const struct file_operations dasd_stats_proc_fops = {
.owner = THIS_MODULE,
.open = dasd_stats_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = dasd_stats_proc_write,
};
/* /*
* Create dasd proc-fs entries. * Create dasd proc-fs entries.
* In case creation failed, cleanup and return -ENOENT. * In case creation failed, cleanup and return -ENOENT.
...@@ -324,13 +316,12 @@ dasd_proc_init(void) ...@@ -324,13 +316,12 @@ dasd_proc_init(void)
&dasd_devices_file_ops); &dasd_devices_file_ops);
if (!dasd_devices_entry) if (!dasd_devices_entry)
goto out_nodevices; goto out_nodevices;
dasd_statistics_entry = create_proc_entry("statistics", dasd_statistics_entry = proc_create("statistics",
S_IFREG | S_IRUGO | S_IWUSR, S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry); dasd_proc_root_entry,
&dasd_stats_proc_fops);
if (!dasd_statistics_entry) if (!dasd_statistics_entry)
goto out_nostatistics; goto out_nostatistics;
dasd_statistics_entry->read_proc = dasd_statistics_read;
dasd_statistics_entry->write_proc = dasd_statistics_write;
return 0; return 0;
out_nostatistics: out_nostatistics:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <asm/asm-offsets.h>
#include <asm/ipl.h> #include <asm/ipl.h>
#include <asm/sclp.h> #include <asm/sclp.h>
#include <asm/setup.h> #include <asm/setup.h>
...@@ -40,12 +41,12 @@ enum arch_id { ...@@ -40,12 +41,12 @@ enum arch_id {
/* dump system info */ /* dump system info */
struct sys_info { struct sys_info {
enum arch_id arch; enum arch_id arch;
unsigned long sa_base; unsigned long sa_base;
u32 sa_size; u32 sa_size;
int cpu_map[NR_CPUS]; int cpu_map[NR_CPUS];
unsigned long mem_size; unsigned long mem_size;
union save_area lc_mask; struct save_area lc_mask;
}; };
struct ipib_info { struct ipib_info {
...@@ -183,52 +184,9 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count) ...@@ -183,52 +184,9 @@ static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
return 0; return 0;
} }
#ifdef __s390x__
/*
* Convert s390x (64 bit) cpu info to s390 (32 bit) cpu info
*/
static void __init s390x_to_s390_regs(union save_area *out, union save_area *in,
int cpu)
{
int i;
for (i = 0; i < 16; i++) {
out->s390.gp_regs[i] = in->s390x.gp_regs[i] & 0x00000000ffffffff;
out->s390.acc_regs[i] = in->s390x.acc_regs[i];
out->s390.ctrl_regs[i] =
in->s390x.ctrl_regs[i] & 0x00000000ffffffff;
}
/* locore for 31 bit has only space for fpregs 0,2,4,6 */
out->s390.fp_regs[0] = in->s390x.fp_regs[0];
out->s390.fp_regs[1] = in->s390x.fp_regs[2];
out->s390.fp_regs[2] = in->s390x.fp_regs[4];
out->s390.fp_regs[3] = in->s390x.fp_regs[6];
memcpy(&(out->s390.psw[0]), &(in->s390x.psw[0]), 4);
out->s390.psw[1] |= 0x8; /* set bit 12 */
memcpy(&(out->s390.psw[4]),&(in->s390x.psw[12]), 4);
out->s390.psw[4] |= 0x80; /* set (31bit) addressing bit */
out->s390.pref_reg = in->s390x.pref_reg;
out->s390.timer = in->s390x.timer;
out->s390.clk_cmp = in->s390x.clk_cmp;
}
static void __init s390x_to_s390_save_areas(void)
{
int i = 1;
static union save_area tmp;
while (zfcpdump_save_areas[i]) {
s390x_to_s390_regs(&tmp, zfcpdump_save_areas[i], i);
memcpy(zfcpdump_save_areas[i], &tmp, sizeof(tmp));
i++;
}
}
#endif /* __s390x__ */
static int __init init_cpu_info(enum arch_id arch) static int __init init_cpu_info(enum arch_id arch)
{ {
union save_area *sa; struct save_area *sa;
/* get info for boot cpu from lowcore, stored in the HSA */ /* get info for boot cpu from lowcore, stored in the HSA */
...@@ -241,20 +199,12 @@ static int __init init_cpu_info(enum arch_id arch) ...@@ -241,20 +199,12 @@ static int __init init_cpu_info(enum arch_id arch)
return -EIO; return -EIO;
} }
zfcpdump_save_areas[0] = sa; zfcpdump_save_areas[0] = sa;
#ifdef __s390x__
/* convert s390x regs to s390, if we are dumping an s390 Linux */
if (arch == ARCH_S390)
s390x_to_s390_save_areas();
#endif
return 0; return 0;
} }
static DEFINE_MUTEX(zcore_mutex); static DEFINE_MUTEX(zcore_mutex);
#define DUMP_VERSION 0x3 #define DUMP_VERSION 0x5
#define DUMP_MAGIC 0xa8190173618f23fdULL #define DUMP_MAGIC 0xa8190173618f23fdULL
#define DUMP_ARCH_S390X 2 #define DUMP_ARCH_S390X 2
#define DUMP_ARCH_S390 1 #define DUMP_ARCH_S390 1
...@@ -279,7 +229,14 @@ struct zcore_header { ...@@ -279,7 +229,14 @@ struct zcore_header {
u32 volnr; u32 volnr;
u32 build_arch; u32 build_arch;
u64 rmem_size; u64 rmem_size;
char pad2[4016]; u8 mvdump;
u16 cpu_cnt;
u16 real_cpu_cnt;
u8 end_pad1[0x200-0x061];
u64 mvdump_sign;
u64 mvdump_zipl_time;
u8 end_pad2[0x800-0x210];
u32 lc_vec[512];
} __attribute__((packed,__aligned__(16))); } __attribute__((packed,__aligned__(16)));
static struct zcore_header zcore_header = { static struct zcore_header zcore_header = {
...@@ -289,7 +246,7 @@ static struct zcore_header zcore_header = { ...@@ -289,7 +246,7 @@ static struct zcore_header zcore_header = {
.dump_level = 0, .dump_level = 0,
.page_size = PAGE_SIZE, .page_size = PAGE_SIZE,
.mem_start = 0, .mem_start = 0,
#ifdef __s390x__ #ifdef CONFIG_64BIT
.build_arch = DUMP_ARCH_S390X, .build_arch = DUMP_ARCH_S390X,
#else #else
.build_arch = DUMP_ARCH_S390, .build_arch = DUMP_ARCH_S390,
...@@ -340,11 +297,7 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count) ...@@ -340,11 +297,7 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
unsigned long prefix; unsigned long prefix;
unsigned long sa_off, len, buf_off; unsigned long sa_off, len, buf_off;
if (sys_info.arch == ARCH_S390) prefix = zfcpdump_save_areas[i]->pref_reg;
prefix = zfcpdump_save_areas[i]->s390.pref_reg;
else
prefix = zfcpdump_save_areas[i]->s390x.pref_reg;
sa_start = prefix + sys_info.sa_base; sa_start = prefix + sys_info.sa_base;
sa_end = prefix + sys_info.sa_base + sys_info.sa_size; sa_end = prefix + sys_info.sa_base + sys_info.sa_size;
...@@ -561,34 +514,39 @@ static const struct file_operations zcore_reipl_fops = { ...@@ -561,34 +514,39 @@ static const struct file_operations zcore_reipl_fops = {
.release = zcore_reipl_release, .release = zcore_reipl_release,
}; };
#ifdef CONFIG_32BIT
static void __init set_s390_lc_mask(union save_area *map) static void __init set_lc_mask(struct save_area *map)
{ {
memset(&map->s390.ext_save, 0xff, sizeof(map->s390.ext_save)); memset(&map->ext_save, 0xff, sizeof(map->ext_save));
memset(&map->s390.timer, 0xff, sizeof(map->s390.timer)); memset(&map->timer, 0xff, sizeof(map->timer));
memset(&map->s390.clk_cmp, 0xff, sizeof(map->s390.clk_cmp)); memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp));
memset(&map->s390.psw, 0xff, sizeof(map->s390.psw)); memset(&map->psw, 0xff, sizeof(map->psw));
memset(&map->s390.pref_reg, 0xff, sizeof(map->s390.pref_reg)); memset(&map->pref_reg, 0xff, sizeof(map->pref_reg));
memset(&map->s390.acc_regs, 0xff, sizeof(map->s390.acc_regs)); memset(&map->acc_regs, 0xff, sizeof(map->acc_regs));
memset(&map->s390.fp_regs, 0xff, sizeof(map->s390.fp_regs)); memset(&map->fp_regs, 0xff, sizeof(map->fp_regs));
memset(&map->s390.gp_regs, 0xff, sizeof(map->s390.gp_regs)); memset(&map->gp_regs, 0xff, sizeof(map->gp_regs));
memset(&map->s390.ctrl_regs, 0xff, sizeof(map->s390.ctrl_regs)); memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs));
} }
static void __init set_s390x_lc_mask(union save_area *map) #else /* CONFIG_32BIT */
static void __init set_lc_mask(struct save_area *map)
{ {
memset(&map->s390x.fp_regs, 0xff, sizeof(map->s390x.fp_regs)); memset(&map->fp_regs, 0xff, sizeof(map->fp_regs));
memset(&map->s390x.gp_regs, 0xff, sizeof(map->s390x.gp_regs)); memset(&map->gp_regs, 0xff, sizeof(map->gp_regs));
memset(&map->s390x.psw, 0xff, sizeof(map->s390x.psw)); memset(&map->psw, 0xff, sizeof(map->psw));
memset(&map->s390x.pref_reg, 0xff, sizeof(map->s390x.pref_reg)); memset(&map->pref_reg, 0xff, sizeof(map->pref_reg));
memset(&map->s390x.fp_ctrl_reg, 0xff, sizeof(map->s390x.fp_ctrl_reg)); memset(&map->fp_ctrl_reg, 0xff, sizeof(map->fp_ctrl_reg));
memset(&map->s390x.tod_reg, 0xff, sizeof(map->s390x.tod_reg)); memset(&map->tod_reg, 0xff, sizeof(map->tod_reg));
memset(&map->s390x.timer, 0xff, sizeof(map->s390x.timer)); memset(&map->timer, 0xff, sizeof(map->timer));
memset(&map->s390x.clk_cmp, 0xff, sizeof(map->s390x.clk_cmp)); memset(&map->clk_cmp, 0xff, sizeof(map->clk_cmp));
memset(&map->s390x.acc_regs, 0xff, sizeof(map->s390x.acc_regs)); memset(&map->acc_regs, 0xff, sizeof(map->acc_regs));
memset(&map->s390x.ctrl_regs, 0xff, sizeof(map->s390x.ctrl_regs)); memset(&map->ctrl_regs, 0xff, sizeof(map->ctrl_regs));
} }
#endif /* CONFIG_32BIT */
/* /*
* Initialize dump globals for a given architecture * Initialize dump globals for a given architecture
*/ */
...@@ -599,21 +557,18 @@ static int __init sys_info_init(enum arch_id arch) ...@@ -599,21 +557,18 @@ static int __init sys_info_init(enum arch_id arch)
switch (arch) { switch (arch) {
case ARCH_S390X: case ARCH_S390X:
pr_alert("DETECTED 'S390X (64 bit) OS'\n"); pr_alert("DETECTED 'S390X (64 bit) OS'\n");
sys_info.sa_base = SAVE_AREA_BASE_S390X;
sys_info.sa_size = sizeof(struct save_area_s390x);
set_s390x_lc_mask(&sys_info.lc_mask);
break; break;
case ARCH_S390: case ARCH_S390:
pr_alert("DETECTED 'S390 (32 bit) OS'\n"); pr_alert("DETECTED 'S390 (32 bit) OS'\n");
sys_info.sa_base = SAVE_AREA_BASE_S390;
sys_info.sa_size = sizeof(struct save_area_s390);
set_s390_lc_mask(&sys_info.lc_mask);
break; break;
default: default:
pr_alert("0x%x is an unknown architecture.\n",arch); pr_alert("0x%x is an unknown architecture.\n",arch);
return -EINVAL; return -EINVAL;
} }
sys_info.sa_base = SAVE_AREA_BASE;
sys_info.sa_size = sizeof(struct save_area);
sys_info.arch = arch; sys_info.arch = arch;
set_lc_mask(&sys_info.lc_mask);
rc = init_cpu_info(arch); rc = init_cpu_info(arch);
if (rc) if (rc)
return rc; return rc;
...@@ -660,8 +615,9 @@ static int __init get_mem_size(unsigned long *mem) ...@@ -660,8 +615,9 @@ static int __init get_mem_size(unsigned long *mem)
static int __init zcore_header_init(int arch, struct zcore_header *hdr) static int __init zcore_header_init(int arch, struct zcore_header *hdr)
{ {
int rc; int rc, i;
unsigned long memory = 0; unsigned long memory = 0;
u32 prefix;
if (arch == ARCH_S390X) if (arch == ARCH_S390X)
hdr->arch_id = DUMP_ARCH_S390X; hdr->arch_id = DUMP_ARCH_S390X;
...@@ -676,6 +632,14 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr) ...@@ -676,6 +632,14 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr)
hdr->num_pages = memory / PAGE_SIZE; hdr->num_pages = memory / PAGE_SIZE;
hdr->tod = get_clock(); hdr->tod = get_clock();
get_cpu_id(&hdr->cpu_id); get_cpu_id(&hdr->cpu_id);
for (i = 0; zfcpdump_save_areas[i]; i++) {
prefix = zfcpdump_save_areas[i]->pref_reg;
hdr->real_cpu_cnt++;
if (!prefix)
continue;
hdr->lc_vec[hdr->cpu_cnt] = prefix;
hdr->cpu_cnt++;
}
return 0; return 0;
} }
...@@ -741,14 +705,21 @@ static int __init zcore_init(void) ...@@ -741,14 +705,21 @@ static int __init zcore_init(void)
if (rc) if (rc)
goto fail; goto fail;
#ifndef __s390x__ #ifdef CONFIG_64BIT
if (arch == ARCH_S390) {
pr_alert("The 64-bit dump tool cannot be used for a "
"32-bit system\n");
rc = -EINVAL;
goto fail;
}
#else /* CONFIG_64BIT */
if (arch == ARCH_S390X) { if (arch == ARCH_S390X) {
pr_alert("The 32-bit dump tool cannot be used for a " pr_alert("The 32-bit dump tool cannot be used for a "
"64-bit system\n"); "64-bit system\n");
rc = -EINVAL; rc = -EINVAL;
goto fail; goto fail;
} }
#endif #endif /* CONFIG_64BIT */
rc = sys_info_init(arch); rc = sys_info_init(arch);
if (rc) if (rc)
......
...@@ -224,8 +224,8 @@ static void ccwreq_log_status(struct ccw_device *cdev, enum io_status status) ...@@ -224,8 +224,8 @@ static void ccwreq_log_status(struct ccw_device *cdev, enum io_status status)
*/ */
void ccw_request_handler(struct ccw_device *cdev) void ccw_request_handler(struct ccw_device *cdev)
{ {
struct irb *irb = (struct irb *)&S390_lowcore.irb;
struct ccw_request *req = &cdev->private->req; struct ccw_request *req = &cdev->private->req;
struct irb *irb = (struct irb *) __LC_IRB;
enum io_status status; enum io_status status;
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
......
...@@ -574,7 +574,7 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page) ...@@ -574,7 +574,7 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
secm_area->request.length = 0x0050; secm_area->request.length = 0x0050;
secm_area->request.code = 0x0016; secm_area->request.code = 0x0016;
secm_area->key = PAGE_DEFAULT_KEY; secm_area->key = PAGE_DEFAULT_KEY >> 4;
secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1; secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1;
secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2; secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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